{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"e1310099-92e2-46e5-b6d1-b2472e0bac51","name":"FIWARE Accessing Context","description":"This tutorial teaches FIWARE users how to alter the context programmatically\n\nThe tutorial builds on the  entities created in the previous \n[stock management example](https://github.com/Fiware/tutorials.Context-Providers/)\nand enables a user understand how to write code in an  [NGSI](https://swagger.lab.fiware.org/?url=https://raw.githubusercontent.com/Fiware/specifications/master/OpenAPI/ngsiv2/ngsiv2-openapi.json)\ncapable [Node.js](https://nodejs.org/) [Express](https://expressjs.com/) application in order to retrieve and alter context \ndata. This removes the need to use the command line to invoke cUrl commands.\n\nThe `docker-compose` file for this tutorial can be found on GitHub: \n\n![GitHub](https://fiware.github.io/tutorials.Accessing-Context/icon/GitHub-Mark-32px.png) [FIWARE 105: Accessing Context Programmatically](https://github.com/Fiware/tutorials.Accessing-Context)\n\n# Accessing the Context Data \n\nFor a typical smart solution you will be retrieving context data from diverse sources (such as a CRM system, social\nnetworks, mobile apps or IoT sensors for example) and then analysing the context programmatically to make appropriate\nbusiness logic decisions. For example in the stock management demo, the application will need to ensure that the prices\npaid for each item always reflect the current price held within the **Product** entity. For a dynamic system, the \napplication will also need to be able to amend the current context. (e.g. creating or updating data or accuating a sensor\nfor example)\n\nIn general terms, three basic scenarios are defined below:\n\n* Reading Data -  e.g. Give me all the data for the **Store** entity `urn:ngsi-ld:Store:001`\n* Aggregation - e.g. Combine the **InventoryItems**  entities for Store `urn:ngsi-ld:Store:001` with \n  the names and prices of the **Product** entities for sale\n* Altering the Context - e.g. Make a sale of a product:\n  + Update the daily sales records by the price of the **Product**\n  + decrement the `shelfCount` of the **InventoryItem** entity\n  + Create a new Transaction Log record showing the sale has occurred\n  + Raise an alert in the warehouse if less than 10 objects remain on sale\n  + etc.\n\nAs you can see the business logic behind each request to access/amend context can range from the simple to complex\ndepending upon business needs.\n\n\n## Making HTTP Requests in the language of your choice\n\nThe [NGSI](http://fiware.github.io/specifications/ngsiv2/latest/) specification defines a language agnostic REST API based on the standard usage of HTTP verbs. Therefore context data can be accessed by any programming language, simply through making HTTP requests. \n\nHere for example is the same HTTP request written in [PHP](https://secure.php.net/), [Node.js](https://Node.js.org/) and [Java](https://www.oracle.com/java/)\n\n\n#### PHP (with `HTTPRequest`)\n\n```php\n<?php\n\n$request = new HttpRequest();\n$request->setUrl('http://localhost:1026/v2/entities/urn:ngsi-ld:Store:001');\n$request->setMethod(HTTP_METH_GET);\n\n$request->setQueryData(array(\n  'options' => 'keyValues'\n));\n\ntry {\n  $response = $request->send();\n\n  echo $response->getBody();\n} catch (HttpException $ex) {\n  echo $ex;\n}\n```\n\n\n#### Node.js (with `request` library)\n\n```javascript\nconst request = require(\"request\");\n\nconst options = { method: 'GET',\n  url: 'http://localhost:1026/v2/entities/urn:ngsi-ld:Store:001',\n  qs: { options: 'keyValues' }};\n\nrequest(options, function (error, response, body) {\n  if (error) throw new Error(error);\n  console.log(body);\n});\n```\n\n\n#### Java (with `CloseableHttpClient` library)\n\n```java\nCloseableHttpClient httpclient = HttpClients.createDefault();\ntry {\n    HttpGet httpget = new HttpGet(\"http://localhost:1026/v2/entities/urn:ngsi-ld:Store:001?options=keyValues\");\n\n    ResponseHandler<String> responseHandler = new ResponseHandler<String>() {\n        @Override\n        public String handleResponse(\n                final HttpResponse response) throws ClientProtocolException, IOException {\n            int status = response.getStatusLine().getStatusCode();\n            if (status >= 200 && status < 300) {\n                HttpEntity entity = response.getEntity();\n                return entity != null ? EntityUtils.toString(entity) : null;\n            } else {\n                throw new ClientProtocolException(\"Unexpected response status: \" + status);\n            }\n        }\n\n    };\n    String body = httpclient.execute(httpget, responseHandler);\n    System.out.println(body);\n} finally {\n    httpclient.close();\n}\n```\n\n## Generating NGSI API Clients\n\nAs you can see from the examples above, each one uses their own programming paradigm to do the following:\n\n* Create a well formed URL.\n* Make an HTTP GET request.\n* Retrieve the response.\n* Check for an error status and throw an exception if necessary.\n* Return the body of the request for further processing.\n\nSince such boilerplate code is frequently re-used it is usually hidden within a library. \n\nThe [`swagger-codegen`](https://github.com/swagger-api/swagger-codegen) tool is able to generate boilerplate API client libraries in a wide variety of programming languages directly from the [NGSI v2 Swagger Specification](https://swagger.lab.fiware.org/?url=https://raw.githubusercontent.com/Fiware/specifications/master/OpenAPI/ngsiv2/ngsiv2-openapi.json)\n\n```console\nswagger-codegen generate \\\n  -l javascript \\\n  -i http://fiware.github.io/specifications/OpenAPI/ngsiv2/ngsiv2-openapi.json \n```\n\nThe generated client can then be used by the code within your own application.\n\n## The teaching goal of this tutorial\n\nThe aim of this tutorial is to improve developer understanding of programmatic access of context data\nthrough defining and discussing a series of generic code examples covering common data access scenarios. \nFor this purpose a simple Node.js Express application will be created.\n\nThe intention here is not to teach users how to write an application in Express - indeed any language could\nhave been chosen. It is merely to show how **any** sample programming language could be used alter the\ncontext to achieve the business logic goals. \n\nObviously, your choice of programming language will depend upon your own business needs - when reading the code\nbelow please keep this in mind and substitute Node.js with your own programming language as appropriate.\n\n\n## Entities within a stock management system\n\nThe relationship between our entities is defined as shown:\n\n![](https://fiware.github.io/tutorials.Accessing-Context/img/entities.png)\n\nThe **Store**, **Product** and **InventoryItem** entities will be used to display data on the front-end of our demo application.\n\n# Architecture\n\nThis application will make use of only one FIWARE component - the [Orion Context Broker](https://catalogue.fiware.org/enablers/publishsubscribe-context-broker-orion-context-broker). Usage of the Orion Context Broker is sufficient for an application to qualify as *“Powered by FIWARE”*.\n\nCurrently, the Orion Context Broker relies on open source [MongoDB](https://www.mongodb.com/) technology to keep\npersistence of the context data it holds. To request context data from external sources, a simple Context Provider NGSI \nproxy has also been added. To visualise and interact with the Context we will add a simple Express application \n\n\nTherefore, the architecture will consist of four elements:\n\n* The Orion Context Broker server which will receive requests using [NGSI](https://swagger.lab.fiware.org/?url=https://raw.githubusercontent.com/Fiware/specifications/master/OpenAPI/ngsiv2/ngsiv2-openapi.json)\n* The underlying MongoDB database associated to the Orion Context Broker server\n* The Context Provider NGSI proxy which will will:\n  + receive requests using  [NGSI](https://swagger.lab.fiware.org/?url=https://raw.githubusercontent.com/Fiware/specifications/master/OpenAPI/ngsiv2/ngsiv2-openapi.json)\n  + makes requests to publicly available data sources using their own APIs in a proprietory format \n  + returns context data back to the Orion Context Broker in  [NGSI](https://swagger.lab.fiware.org/?url=https://raw.githubusercontent.com/Fiware/specifications/master/OpenAPI/ngsiv2/ngsiv2-openapi.json) format.\n* The Stock Management Frontend which will will:\n  + Display store information\n  + Show which products can be bought at each store\n  + Allow users to \"buy\" products and reduce the stock count.\n\nSince all interactions between the elements are initiated by HTTP requests, the entities can be containerized and run\nfrom exposed ports. \n\n![](https://fiware.github.io/tutorials.Accessing-Context/img/architecture.png)\n\nThe necessary configuration information can be seen in the services section of the associated `docker-compose.yml` file. It\nhas been described in a [previous tutorial](https://github.com/Fiware/tutorials.Context-Providers/)\n\n\n# Prerequisites\n\n## Docker\n\nTo keep things simple both components will be run using [Docker](https://www.docker.com). **Docker** is a container technology\nwhich allows to different components isolated into their respective environments. \n\n* To install Docker on Windows follow the instructions [here](https://docs.docker.com/docker-for-windows/)\n* To install Docker on Mac follow the instructions [here](https://docs.docker.com/docker-for-mac/)\n* To install Docker on Linux follow the instructions [here](https://docs.docker.com/install/)\n\n**Docker Compose** is a tool for defining and running multi-container Docker applications. A \n[YAML file](https://raw.githubusercontent.com/Fiware/tutorials.Entity-Relationships/master/docker-compose.yml) is used\nconfigure the required services for the application. This means all container sevices can be brought up in a single \ncommmand. Docker Compose is installed by default  as part of Docker for Windows and  Docker for Mac, however Linux users \nwill need to follow the instructions found  [here](https://docs.docker.com/compose/install/)\n\n## Cygwin \n\nWe will start up our services using a simple bash script. Windows users should download [cygwin](www.cygwin.com) to provide a\ncommand line functionality similar to a Linux distribution on Windows. \n\n# Start Up\n\nAll services can be initialised from the command line by running the bash script provided within the repository:\n\n```console\n./services create; ./services start;\n```\n\nThis command will also import seed data from the previous [Stock Management example](https://github.com/Fiware/tutorials.Context-Providers) on startup.\n\n>:information_source: **Note:** If you want to clean up and start over again you can do so with the following command:\n>\n>```console\n>./services stop\n>``` \n>\n\n#  Stock Management Frontend\n\nAll the code Node.js Express for the demo can be found within the `proxy` folder within the GitHub repository.[Stock Management example](https://github.com/Fiware/tutorials.Accessing-Context/tree/master/proxy). The application runs on the following URLs:\n\n\n* `http://localhost:3000/app/store/urn:ngsi-ld:Store:001`\n* `http://localhost:3000/app/store/urn:ngsi-ld:Store:002`\n* `http://localhost:3000/app/store/urn:ngsi-ld:Store:003`\n* `http://localhost:3000/app/store/urn:ngsi-ld:Store:004`\n\n\n>:information_source: **Tip**  Additionally, you can also watch the status of recent requests yourself by\n>following the container logs or viewing information on `localhost:3000/app/monitor` on a web browser.\n>\n>![FIWARE Monitor](https://fiware.github.io/tutorials.Accessing-Context/img/monitor.png)\n\n\n## NGSI v2 npm library\n\nAn NGSI v2 compatible [npm library](https://github.com/smartsdk/ngsi-sdk-javascript) has been developed by the\n[SmartSDK](https://www.smartsdk.eu/) team. This is a callback-based library which will be used to take care of\nour low level HTTP requests and will simplify the code to be written. The methods exposed in the library map\ndirectly onto the NGSI v2 [CRUD operations](https://github.com/Fiware/tutorials.CRUD-Operations#what-is-crud)\nwith the following names:\n\n| HTTP Verb   | `/v2/entities`  | `/v2/entities/<entity>`  |\n|-----------  |:--------------: |:-----------------------: |\n| **POST**    | [`createEntity()`](https://github.com/smartsdk/ngsi-sdk-javascript/blob/master/docs/EntitiesApi.md#createEntity)  | Not used  |\n| **GET**     | [`listEntities()`](https://github.com/smartsdk/ngsi-sdk-javascript/blob/master/docs/EntitiesApi.md#listEntities) | [`retrieveEntity()`](https://github.com/smartsdk/ngsi-sdk-javascript/blob/master/docs/EntitiesApi.md#retrieveEntity)  | \n| **PUT**     | Not used   | Not used  |\n| **PATCH**   | Not used   | Not used   |\n| **DELETE**  | Not used  | [`removeEntity()`](https://github.com/smartsdk/ngsi-sdk-javascript/blob/master/docs/EntitiesApi.md#removeEntity)  | \n\n\n\n| HTTP Verb   | `.../attrs`  | `.../attrs/<attribute>`  | `.../attrs/<attribute>/value`  |\n|-----------  |:-----------: |:-----------------------: |:-----------------------------: |\n| **POST**    |  [`updateOrAppendEntityAttributes()`](https://github.com/smartsdk/ngsi-sdk-javascript/blob/master/docs/EntitiesApi.md#updateOrAppendEntityAttributes)   | Not used  | Not used   |\n| **GET**     |  [`retrieveEntityAttributes()`](https://github.com/smartsdk/ngsi-sdk-javascript/blob/master/docs/EntitiesApi.md#retrieveEntityAttributes)  | Not used   | [`getAttributeValue()`](https://github.com/smartsdk/ngsi-sdk-javascript/blob/master/docs/AttributeValueApi.md#getAttributeValue)  |\n| **PUT**     |  Not used  | Not used   | [`updateAttributeValue()`](https://github.com/smartsdk/ngsi-sdk-javascript/blob/master/docs/AttributeValueApi.md#updateAttributeValue)  |\n| **PATCH**   |  [`updateExistingEntityAttributes()`](https://github.com/smartsdk/ngsi-sdk-javascript/blob/master/docs/EntitiesApi.md#updateExistingEntityAttributes) | Not used  | Not used   |\n| **DELETE**. |  Not used | `removeASingleAttribute()` | Not used  |\n\n\n## Analysing the Code\n\nThe code under discussion can be found within the `store` controller in the [Git Repository](https://github.com/Fiware/tutorials.Context-Providers/blob/master/proxy/controllers/store.js)\n\n### Initializing the library\n\nWe don't want to reinvent the wheel and spend time writing a unnecessary boilerplate code for HTTP access. Therefore\nwe will use the exising `ngsi_v2`  NPM library. This needs to be included in the header of the file as shown. The\n`basePath` must also be set - this defines the location of the Orion Context Broker. \n\n```javascript\nconst NgsiV2 = require('ngsi_v2');\nconst defaultClient = NgsiV2.ApiClient.instance;\ndefaultClient.basePath = process.env.CONTEXT_BROKER || 'http://localhost:1026/v2';\n```\n\n\n### Reading Store Data\n\nThis example reads the context data of a given **Store** entity to display the results on screen.\nReading entity data can be done using the `apiInstance.retrieveEntity()` method. Since the library uses callbacks,\nthey have been wrapped by a `Promise` function as shown below. The libary function `apiInstance.retrieveEntity()` \nwill fill out the URL for the GET request and make the necessary HTTP call:\n\n```javascript\nfunction retrieveEntity(entityId, opts) {\n  return new Promise(function(resolve, reject) {\n    const apiInstance = new NgsiV2.EntitiesApi();\n    apiInstance.retrieveEntity(entityId, opts, (error, data) => {\n      return error ? reject(error) : resolve(data);\n    });\n  });\n}\n```\n\n\nThis enables us to wrap the requests in `Promises` as shown:\n\n```javascript\nfunction displayStore(req, res) {\n  retrieveEntity(\n    req.params.storeId, { options: 'keyValues', type: 'Store' })\n  .then(store => {\n    // If a store has been found display it on screen\n    return res.render('store', { title: store.name, store});\n  })\n  .catch(error => {\n    debug(error);\n    // If no store has been found, display an error screen\n      return res.render('store-error', {title: 'Error', error});\n  });\n}\n```\n\nIndirectly this is making an HTTP GET request to `http://{{orion}}/v2/entities/<store-id>?type=Store&options=keyValues`.\nNote the re-use of the Store URN in the incoming request.\n\nThe equivalent cUrl command would be as shown:\n\n```console\ncurl -X GET \\\n  'http://{{orion}}/v2/entities/urn:ngsi-ld:Store:001?options=keyValues'\n```\n\nThe response will be as shown below:\n\n```json\n{\n    \"id\": \"urn:ngsi-ld:Store:001\",\n    \"type\": \"Store\",\n    \"address\": {\n        \"streetAddress\": \"Bornholmer Straße 65\",\n        \"addressRegion\": \"Berlin\",\n        \"addressLocality\": \"Prenzlauer Berg\",\n        \"postalCode\": \"10439\"\n    },\n    \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [\n            13.3986,\n            52.5547\n        ]\n    },\n    \"name\": \"Bösebrücke Einkauf\"\n}\n```\n\nThe store data from the HTTP response body is then passed to the PUG rendering engine to display on screen as\nshown below:\n\n#### `http://localhost:3000/app/store/urn:ngsi-ld:Store:005`\n\n![Store 1](https://fiware.github.io/tutorials.Accessing-Context/img/store.png)\n\nFor efficiency, it is important to request as few attributes as possible, in order to reduce network traffic.\nThis optimization has not been made in the code yet.\n\nAn error handler is necessary in case the context data is not available - for example if a user queries for a\nstore that does not exist. This will forward to an error page as shown:\n\n#### `http://localhost:3000/app/store/urn:ngsi-ld:Store:005`\n\n![Store 5](https://fiware.github.io/tutorials.Accessing-Context/img/store-error.png)\n\nThe equivalent cUrl command would be as shown:\n\n```console\ncurl -X GET \\\n  'http://{{orion}}/v2/entities/urn:ngsi-ld:Store:001?options=keyValues'\n```\n\nThe response has a status of **404 Not Found** with a body as shown below:\n\n```json\n{\n    \"error\": \"NotFound\",\n    \"description\": \"The requested entity has not been found. Check type and id\"\n}\n```\n\nThe `error` object in the `catch` method hold the error response. This is then displayed on the front end.\n\n\n### Aggregating Products and Inventory Items\n\nThis example reads the context data of the current **InventoryItem** entities for a given store and combines\nthe information with the prices from the **Product** entities. The result is information to be displayed on\nthe cash till.\n\n![Till](https://fiware.github.io/tutorials.Accessing-Context/img/till.png)\n\nMultiple entities can be requested and aggregated by creating a `Promise` chain or by usign `Promise.all`. \nHere the **Product**  and **InventoryItems** entities have been requested using the `apiInstance.listEntities()` \nlibrary method. The presence of the `q` parameter in the request will filter the list of entities received. \n\n\n```javascript\nfunction displayTillInfo(req, res) {\n  Promise.all([ \n    listEntities({\n    options: 'keyValues',\n    type: 'Product',\n  }), listEntities({\n    q: 'refStore==' + req.params.storeId,\n    options: 'keyValues',\n    type: 'InventoryItem',\n  })])\n  .then(values => {\n    // If values have been found display it on screen\n    return res.render('till', { products : values[0], inventory : values[1] });\n  })\n  .catch(error => {\n    debug(error);\n    // An error occurred, return with no results\n    return res.render('till', { products : {}, inventory : {}});\n  });\n}\n\n\nfunction listEntities(opts) {\n  return new Promise(function(resolve, reject) {\n    const apiInstance = new NgsiV2.EntitiesApi();\n    apiInstance.listEntities(opts, (error, data) => {\n      return error ? reject(error) : resolve(data);\n    });\n  });\n}\n```\n\n\nThe code used for aggregating the results (displaying the product names for each item stocked) has been delegated\nto a `mixin` on the front-end. The foreign key aggregation (`item.refProduct === product.id`) could have been\nadded to the Node.js code if we were passing on aggregated data to another component:\n\n```pug\nmixin product(item, products)\n  each product in products\n    if (item.refProduct === product.id)\n      span(id=`${product.id}`)\n        strong\n          | #{product.name}\n\n        | &nbsp; @ #{product.price /100} &euro; each\n        | - #{item.shelfCount} in stock\n        |\n\n```\n\n\nAgain an error handler has been created to ensure that if any of the HTTP requests to the Orion Context Broker fail, an empty list of products is returned. \n\nRetrieving the full list of **Product** entities for each request is not efficient. It would be better to load the list of products from cache, and only update the list if prices have changed. This could be achieved using the NGSI Subscription mechanism which is the subject of a subsequent tutorial.\n\n### Updating Context\n\nBuying an item will involve decrementing the number of items left on a shelf. The example consists of two linked requests.\nThe reading of the **InventoryItem** entity data can be done using the `apiInstance.retrieveEntity()` method as shown \npreviously. The data is then ammended  in memory before being sent to the Orion Context Broker using the \n`apiInstance.updateExistingEntityAttributes()` method.  This is effectively just a wrapper around an HTTP PATCH request to\n`http://{{orion}}/v2/entities/<inventory-id>?type=InventoryItem`, with a body containing the elements to be updated.\nThere is no error handling on this function, it has been left to a function on the router.\n\n\n```javascript\nasync function buyItem(req, res) {\n  const inventory = await retrieveEntity(req.params.inventoryId, {\n    options: 'keyValues',\n    type: 'InventoryItem',\n  });\n  const count = inventory.shelfCount - 1;\n  await updateExistingEntityAttributes(\n    req.params.inventoryId,\n    { shelfCount: { type: 'Integer', value: count } },\n    {\n      type: 'InventoryItem',\n    }\n  );\n  res.redirect(`/app/store/${inventory.refStore}/till`);\n}\n\nfunction updateExistingEntityAttributes(entityId, body, opts) {\n  return new Promise(function(resolve, reject) {\n    const apiInstance = new NgsiV2.EntitiesApi();\n    apiInstance.updateExistingEntityAttributes(entityId, body, opts, (error, data) => {\n      return error ? reject(error) : resolve(data);\n    });\n  });\n}\n```\n\n\nCare should be taken when amending the context to ensure that changes of state are committed atomically. This is not an issue in Node.JS since it is single threaded - each request but will execute each request one by one. However in multithreaded environments (such as Java for example) it could be possible to service two buy requests concurrently - meaning that the `shelfCount` will only be reduced once if the requests interleave. This issue can be resolved by the use of a monitor mechanism.\n\nThis is the equivalent of the following cURL commands (plus some business logic)\n\n```\ncurl -X GET \\\n  'http://localhost:1026/v2/entities/urn:ngsi-ld:InventoryItem:001/attrs/shelfCount/value'\ncurl -X PATCH \\\n  'http://localhost:1026/v2/entities/urn:ngsi-ld:InventoryItem:006/attrs' \\\n  -H 'Cache-Control: no-cache' \\\n  -H 'Content-Type: application/json' \\\n  -H 'Postman-Token: af6d60fe-ef9f-4d54-8382-3ddd48d43b82' \\\n  -d '{ \"shelfCount\": \n  { \"type\": \"Integer\", \"value\": \"13\" } \n}'\n```\n\n\n\n\n\n\n\n\n\n\n\n","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":true,"owner":"513743","team":157450,"collectionId":"e1310099-92e2-46e5-b6d1-b2472e0bac51","publishedId":"RW1bnetD","public":true,"publicUrl":"https://documenter-api.postman.tech/view/513743/RW1bnetD","privateUrl":"https://go.postman.co/documentation/513743-e1310099-92e2-46e5-b6d1-b2472e0bac51","customColor":{"top-bar":"FFFFFF","right-sidebar":"4C4C4C","highlight":"233C68"},"documentationLayout":"classic-double-column","version":"8.10.1","publishDate":"2020-01-02T11:02:28.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{},"logos":{}},"statusCode":200},"environments":[],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/d7085d490b9144732c65203aa6e3b68b31884d1c33a86b8a00d15da75147ae33","favicon":""},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"}],"canonicalUrl":"https://documenter.gw.postman.com/view/metadata/RW1bnetD"}