Google Place Rest API

A rest API flow that wraps the Google Places API.

This flow makes use of the Google Web Nodes (https://github.com/node-red/node-red-web-nodes/tree/master/google)

Prerequisites

  • First, you will need to install the Google Web Nodes.

      npm install node-red-node-google
    
  • The Google Places API requires a Google Developer API key. You will need to create a project with Google in order to obtain one. (https://code.google.com/apis/console/)

  • This flow also contains additional swagger documentation. This is to be used with the Node Red Swagger Plugin (https://github.com/node-red/node-red-node-swagger)

      npm install node-red-node-swagger
    

Usage

The flow will create an HTTP endpoint for all three types of Google Places API requests. Each endpoint will direct the user to a different API request. You can make changes to the Google Places node's configuration if you would like to include any information ahead of time, like API key for instance. All properties taken by the Google Places node can be passed as msg level parameters. The Google Places node is heavily documented, and details about possible parameters can be acquired via the info tab. All errors that occur will be relayed back to the user via the catch node.

[
  {
    "id": "261fda9.28adba6",
    "type": "swagger-doc",
    "summary": "Google Places Details Search",
    "description": "If passed a placeid, the assembly will perform a Places Details request, to get more details about a given business.",
    "tags": "GooglePlaces",
    "consumes": "application\/json",
    "produces": "application\/json",
    "parameters": [
      {
        "name": "key",
        "in": "query",
        "description": "Your application's API key. This key identifies your application for purposes of quota management. (https:\/\/code.google.com\/apis\/console\/)",
        "required": true,
        "type": "string"
      },
      {
        "name": "placeid",
        "in": "query",
        "description": "A unique identifier that is returned from a Google Places request.",
        "required": true,
        "type": "string"
      },
      {
        "name": "language",
        "in": "query",
        "description": "The language in which to return results.",
        "required": false,
        "type": "string"
      },
      {
        "name": "extension",
        "in": "query",
        "description": "Indicates if the Place Details response should include additional fields. Additional fields may include Premium data, requiring an additional license, or values that are not commonly requested. Extensions are currently experimental. Supported values for the extensions parameter are {review_summary}.",
        "required": false,
        "type": "string"
      }
    ],
    "responses": {
      "200": {
        "description": "Detailed decription of the requested business.",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "result": {
              "type": "string"
            }
          }
        }
      },
      "400": {
        "description": "Your request was malformed, either by missing or incorrect parameters.",
        "schema": {
          "properties": {
            "error": {
              "type": "string"
            },
            "status": {
              "type": "string"
            }
          }
        }
      },
      "401": {
        "description": "You provided an API Key that is invalid, or is not authorized to use the Google Places API",
        "schema": {
          "properties": {
            "error": {
              "type": "string"
            },
            "status": {
              "type": "string"
            }
          }
        }
      },
      "429": {
        "description": "You have used the daily allotment of Google Places requests for the provided API Key.",
        "schema": {
          "properties": {
            "error": {
              "type": "string"
            },
            "status": {
              "type": "string"
            }
          }
        }
      },
      "500": {
        "description": "An unknown error occurred. Please try your request again.",
        "schema": {
          "properties": {
            "error": {
              "type": "string"
            },
            "status": {
              "type": "string"
            }
          }
        }
      }
    },
    "deprecated": false
  },
  {
    "id": "fe328b6d.c4f568",
    "type": "swagger-doc",
    "summary": "Google Places Text Search",
    "description": "If passed a query string, the assembly will perform a Places Text request, allowing Google to process natural language and return matching businesses (eg. \\\"Restaurants in Sydney\\\").",
    "tags": "GooglePlaces",
    "consumes": "application\/json",
    "produces": "application\/json",
    "parameters": [
      {
        "name": "key",
        "in": "query",
        "description": "Your application's API key. This key identifies your application for purposes of quota management. (https:\/\/code.google.com\/apis\/console\/)",
        "required": true,
        "type": "string"
      },
      {
        "name": "query",
        "in": "query",
        "description": "The text string on which to search, for example: \"restaurant\". The Google Places service will return candidate matches based on this string and order the results based on their perceived relevance.",
        "required": true,
        "type": "string"
      },
      {
        "name": "lat",
        "in": "query",
        "description": "Latitude point to be sent to Google to be used as the center point for the request.",
        "required": false,
        "type": "number"
      },
      {
        "name": "lon",
        "in": "query",
        "description": "Longitude point to be sent to Google to be used as the center point for the request.",
        "required": false,
        "type": "number"
      },
      {
        "name": "radius",
        "in": "query",
        "description": "Defines the distance (in meters) within which to return place results. The maximum allowed radius is 50000 meters.",
        "required": false,
        "type": "integer"
      },
      {
        "name": "language",
        "in": "query",
        "description": "The language in which to return results.",
        "required": false,
        "type": "string"
      },
      {
        "name": "minprice",
        "in": "query",
        "description": "Restricts results to only those places within the specified price level. Valid values are in the range from 0 (most affordable) to 4 (most expensive), inclusive.",
        "required": false,
        "type": "string"
      },
      {
        "name": "maxprice",
        "in": "query",
        "description": "Restricts results to only those places within the specified price level. Valid values are in the range from 0 (most affordable) to 4 (most expensive), inclusive.",
        "required": false,
        "type": "string"
      },
      {
        "name": "types",
        "in": "query",
        "description": "Restricts the results to places matching at least one of the specified types. Types should be separated with a pipe symbol (type1|type2|etc). (https:\/\/developers.google.com\/places\/documentation\/supported_types for supported types)",
        "required": false,
        "type": "string"
      },
      {
        "name": "opennow",
        "in": "query",
        "description": "If set to true, will only return results that are currently open now.",
        "required": false,
        "type": "boolean"
      }
    ],
    "responses": {
      "200": {
        "description": "An array of results matching the supplied parameters.",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "results": {
              "type": "string"
            }
          }
        }
      },
      "400": {
        "description": "Your request was malformed, either by missing or incorrect parameters.",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "error": {
              "type": "string"
            }
          }
        }
      },
      "401": {
        "description": "You provided an API Key that is invalid, or is not authorized to use the Google Places API.",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "error": {
              "type": "string"
            }
          }
        }
      },
      "429": {
        "description": "You have used the daily allotment of Google Places requests for the provided API Key.",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "error": {
              "type": "string"
            }
          }
        }
      },
      "500": {
        "description": "An unknown error occurred. Please try your request again.",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "error": {
              "type": "string"
            }
          }
        }
      }
    },
    "deprecated": false
  },
  {
    "id": "593b6d9.9c69a14",
    "type": "swagger-doc",
    "summary": "Google Places Nearby Search",
    "description": "If passed a latitude\/longitude coordinate set, the assembly will perform a Places Nearby request, to discover businesses within a certain distance of the given location.",
    "tags": "GooglePlaces",
    "consumes": "application\/json",
    "produces": "application\/json",
    "parameters": [
      {
        "name": "key",
        "in": "query",
        "description": "Your application's API key. This key identifies your application for purposes of quota management. (https:\/\/code.google.com\/apis\/console\/)",
        "required": true,
        "type": "string"
      },
      {
        "name": "lat",
        "in": "query",
        "description": "Latitude point to be sent to Google to be used as the center point for the request.",
        "required": true,
        "type": "number"
      },
      {
        "name": "lon",
        "in": "query",
        "description": "Longitude point to be sent to Google to be used as the center point for the request.",
        "required": true,
        "type": "number"
      },
      {
        "name": "radius",
        "in": "query",
        "description": "Defines the distance (in meters) within which to return place results. The maximum allowed radius is 50000 meters. (Required if rankby=prominence. If rankby=distance, radius is not allowed)",
        "required": false,
        "type": "integer"
      },
      {
        "name": "keyword",
        "in": "query",
        "description": "A term to be matched against all content that Google has indexed for this place, including but not limited to name, type, and address, as well as customer reviews and other third-party content.",
        "required": false,
        "type": "string"
      },
      {
        "name": "language",
        "in": "query",
        "description": "The language in which to return results.",
        "required": false,
        "type": "string"
      },
      {
        "name": "minprice",
        "in": "query",
        "description": "Restricts results to only those places within the specified price level. Valid values are in the range from 0 (most affordable) to 4 (most expensive), inclusive.",
        "required": false,
        "type": "integer"
      },
      {
        "name": "maxprice",
        "in": "query",
        "description": "Restricts results to only those places within the specified price level. Valid values are in the range from 0 (most affordable) to 4 (most expensive), inclusive.",
        "required": false,
        "type": "integer"
      },
      {
        "name": "name",
        "in": "query",
        "description": "The name of the business to search for.",
        "required": false,
        "type": "string"
      },
      {
        "name": "types",
        "in": "query",
        "description": "Restricts the results to places matching at least one of the specified types. Types should be separated with a pipe symbol (type1|type2|etc). (https:\/\/developers.google.com\/places\/documentation\/supported_types for supported types)",
        "required": false,
        "type": "string"
      },
      {
        "name": "opennow",
        "in": "query",
        "description": "If set to true, will only return results that are currently open now.",
        "required": false,
        "type": "boolean"
      }
    ],
    "responses": {
      "200": {
        "description": "An array of results matching the supplied parameters.",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "results": {
              "type": "string"
            }
          }
        }
      },
      "400": {
        "description": "Your request was malformed, either by missing or incorrect parameters.",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "error": {
              "type": "string"
            }
          }
        }
      },
      "401": {
        "description": "You provided an API Key that is invalid, or is not authorized to use the Google Places API",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "error": {
              "type": "string"
            }
          }
        }
      },
      "429": {
        "description": "You have used the daily allotment of Google Places requests for the provided API Key.",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "error": {
              
            }
          }
        }
      },
      "500": {
        "description": "An unknown error occurred. Please try your request again.",
        "schema": {
          "properties": {
            "status": {
              "type": "string"
            },
            "error": {
              "type": "string"
            }
          }
        }
      }
    },
    "deprecated": false
  },
  {
    "id": "cbe10941.d35978",
    "type": "catch",
    "name": "",
    "x": 108,
    "y": 367,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "684c042b.1ea75c"
      ]
    ]
  },
  {
    "id": "684c042b.1ea75c",
    "type": "function",
    "name": "Move error to http-out",
    "func": "var error = msg._error;\nmsg.payload = error;\nif(error){\n    msg.statusCode = error.code || 500;\n} else{\n    msg.statusCode = 500;\n}\nreturn msg;",
    "outputs": 1,
    "x": 333,
    "y": 367,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "19cdd193.3c105e"
      ]
    ]
  },
  {
    "id": "19cdd193.3c105e",
    "type": "http response",
    "name": "",
    "x": 523,
    "y": 367,
    "z": "a37c852.f41b9f8",
    "wires": [
      
    ]
  },
  {
    "id": "4305045c.0c1d54",
    "type": "http in",
    "name": "",
    "url": "\/places\/nearby",
    "method": "get",
    "swaggerDoc": "593b6d9.9c69a14",
    "x": 187,
    "y": 159,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "8e4d57b.7d2cfa8"
      ]
    ]
  },
  {
    "id": "41a8416f.3ee9",
    "type": "http response",
    "name": "",
    "x": 1306,
    "y": 203,
    "z": "a37c852.f41b9f8",
    "wires": [
      
    ]
  },
  {
    "id": "8e4d57b.7d2cfa8",
    "type": "function",
    "name": "Move Query Params to Msg",
    "func": "msg.location = {};\nif(msg.req.query.lat || msg.req.query.lon){\n\tmsg.location.lat = msg.req.query.lat;\n\tmsg.location.lon = msg.req.query.lon;\n}\nif(msg.req.query.key){\n\tmsg.key = msg.req.query.key;\n}\nif(msg.req.query.radius){\n\tmsg.location.radius = msg.req.query.radius;\n}\nif(msg.req.query.rankby){\n\tmsg.rankby = msg.req.query.rankby;\n}\nif(msg.req.query.keyword){\n\tmsg.keyword = msg.req.query.keyword;\n}\nif(msg.req.query.language){\n\tmsg.language = msg.req.query.language;\n}\nif(msg.req.query.minprice){\n\tmsg.minprice = msg.req.query.minprice;\n}\nif(msg.req.query.maxprice){\n\tmsg.maxprice = msg.req.query.maxprice;\n}\nif(msg.req.query.name){\n\tmsg.name = msg.req.query.name;\n}\nif(msg.req.query.types){\n\tmsg.types = msg.req.query.types;\n}\nif(msg.req.query.opennow){\n\tmsg.opennow = msg.req.query.opennow;\n}\nif(msg.req.query.zagatselected){\n\tmsg.zagatselected = msg.req.query.zagatselected;\n}\nif(msg.req.query.extensions){\n\tmsg.extensions = msg.req.query.extensions;\n}\ndelete msg.payload;\nreturn msg;",
    "outputs": 1,
    "x": 495,
    "y": 159,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "71b17ddb.2a3bcc"
      ]
    ]
  },
  {
    "id": "11d22936.c8c597",
    "type": "google places",
    "reqType": "placesText",
    "googleAPI": "",
    "name": "",
    "lat": "",
    "lon": "",
    "query": "",
    "radius": "",
    "rankBy": "",
    "keyword": "",
    "language": "",
    "minPrice": "",
    "maxPrice": "",
    "placeName": "",
    "placeId": "",
    "extensions": "",
    "openNow": false,
    "types": "",
    "outputnumber": "20",
    "outputas": "single",
    "x": 780,
    "y": 210,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "ba4fc504.5d70f"
      ]
    ]
  },
  {
    "id": "fdf08290.07906",
    "type": "google places",
    "reqType": "placesDetails",
    "googleAPI": "",
    "name": "",
    "lat": "",
    "lon": "",
    "query": "",
    "radius": "",
    "rankBy": "",
    "keyword": "",
    "language": "",
    "minPrice": "",
    "maxPrice": "",
    "placeName": "",
    "placeId": "",
    "extensions": "",
    "openNow": "",
    "types": "",
    "outputnumber": "20",
    "outputas": "single",
    "x": 780,
    "y": 257,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "afe3a964.6655d8"
      ]
    ]
  },
  {
    "id": "af58d24d.936c38",
    "type": "function",
    "name": "Convert msg to http out",
    "func": "if(typeof(msg.payload) == typeof([])){\n    var results = [];\n    for(var i = 0; i < msg.payload.length; i++){\n\t    results[i] = msg.payload[i].payload;\n    }\n    msg.payload = {\n    \tresults: results,\n    \tstatus: msg.status,\n    };\n}\n\nif(msg.html_attributions){\n\tmsg.payload.html_attributions = msg.html_attributions;\n}\nreturn msg;",
    "outputs": 1,
    "x": 1076,
    "y": 171,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "41a8416f.3ee9"
      ]
    ]
  },
  {
    "id": "71b17ddb.2a3bcc",
    "type": "google places",
    "reqType": "placesNearby",
    "googleAPI": "",
    "name": "",
    "lat": "",
    "lon": "",
    "query": "",
    "radius": "",
    "rankBy": "",
    "keyword": "",
    "language": "",
    "minPrice": "",
    "maxPrice": "",
    "placeName": "",
    "placeId": "",
    "extensions": "",
    "openNow": false,
    "types": "",
    "outputnumber": "20",
    "outputas": "single",
    "x": 777,
    "y": 159,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "af58d24d.936c38"
      ]
    ]
  },
  {
    "id": "b1d63a8f.f29438",
    "type": "function",
    "name": "Move Query Params to Msg",
    "func": "msg.location = {};\nif(msg.req.query.lat || msg.req.query.lon){\n\tmsg.location.lat = msg.req.query.lat;\n\tmsg.location.lon = msg.req.query.lon;\n}\nif(msg.req.query.key){\n\tmsg.key = msg.req.query.key;\n}\nif(msg.req.query.radius){\n\tmsg.location.radius = msg.req.query.radius;\n}\nif(msg.req.query.rankby){\n\tmsg.rankby = msg.req.query.rankby;\n}\nif(msg.req.query.keyword){\n\tmsg.keyword = msg.req.query.keyword;\n}\nif(msg.req.query.language){\n\tmsg.language = msg.req.query.language;\n}\nif(msg.req.query.minprice){\n\tmsg.minprice = msg.req.query.minprice;\n}\nif(msg.req.query.maxprice){\n\tmsg.maxprice = msg.req.query.maxprice;\n}\nif(msg.req.query.name){\n\tmsg.name = msg.req.query.name;\n}\nif(msg.req.query.types){\n\tmsg.types = msg.req.query.types;\n}\nif(msg.req.query.opennow){\n\tmsg.opennow = msg.req.query.opennow;\n}\nif(msg.req.query.zagatselected){\n\tmsg.zagatselected = msg.req.query.zagatselected;\n}\nif(msg.req.query.query){\n\tmsg.query = msg.req.query.query;\n}\nif(msg.req.query.extensions){\n\tmsg.extensions = msg.req.query.extensions;\n}\ndelete msg.payload;\nreturn msg;",
    "outputs": 1,
    "x": 497,
    "y": 210,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "11d22936.c8c597"
      ]
    ]
  },
  {
    "id": "4a683e2f.fefc2",
    "type": "function",
    "name": "Move Query Params to Msg",
    "func": "msg.location = {};\nif(msg.req.query.lat || msg.req.query.lon){\n\tmsg.location.lat = msg.req.query.lat;\n\tmsg.location.lon = msg.req.query.lon;\n}\nif(msg.req.query.key){\n\tmsg.key = msg.req.query.key;\n}\nif(msg.req.query.radius){\n\tmsg.location.radius = msg.req.query.radius;\n}\nif(msg.req.query.rankby){\n\tmsg.rankby = msg.req.query.rankby;\n}\nif(msg.req.query.keyword){\n\tmsg.keyword = msg.req.query.keyword;\n}\nif(msg.req.query.language){\n\tmsg.language = msg.req.query.language;\n}\nif(msg.req.query.minprice){\n\tmsg.minprice = msg.req.query.minprice;\n}\nif(msg.req.query.maxprice){\n\tmsg.maxprice = msg.req.query.maxprice;\n}\nif(msg.req.query.name){\n\tmsg.name = msg.req.query.name;\n}\nif(msg.req.query.types){\n\tmsg.types = msg.req.query.types;\n}\nif(msg.req.query.opennow){\n\tmsg.opennow = msg.req.query.opennow;\n}\nif(msg.req.query.zagatselected){\n\tmsg.zagatselected = msg.req.query.zagatselected;\n}\nif(msg.req.query.placeid){\n\tmsg.placeid = msg.req.query.placeid;\n}\nif(msg.req.query.extensions){\n\tmsg.extensions = msg.req.query.extensions;\n}\ndelete msg.payload;\nreturn msg;",
    "outputs": 1,
    "x": 502,
    "y": 257,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "fdf08290.07906"
      ]
    ]
  },
  {
    "id": "d0da304b.9e05d8",
    "type": "http in",
    "name": "",
    "url": "\/places\/text",
    "method": "get",
    "swaggerDoc": "fe328b6d.c4f568",
    "x": 182,
    "y": 210,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "b1d63a8f.f29438"
      ]
    ]
  },
  {
    "id": "7c6bf57.f65d28c",
    "type": "http in",
    "name": "",
    "url": "\/places\/details",
    "method": "get",
    "swaggerDoc": "261fda9.28adba6",
    "x": 188,
    "y": 257,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "4a683e2f.fefc2"
      ]
    ]
  },
  {
    "id": "ba4fc504.5d70f",
    "type": "function",
    "name": "Convert msg to http out",
    "func": "if(typeof(msg.payload) == typeof([])){\n    var results = [];\n    for(var i = 0; i < msg.payload.length; i++){\n\t    results[i] = msg.payload[i].detailsJson;\n    }\n    msg.payload = {\n    \tresults: results,\n    \tstatus: msg.status,\n    };\n}\n\nif(msg.html_attributions){\n\tmsg.payload.html_attributions = msg.html_attributions;\n}\nreturn msg;",
    "outputs": 1,
    "x": 1073,
    "y": 212,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "41a8416f.3ee9"
      ]
    ]
  },
  {
    "id": "afe3a964.6655d8",
    "type": "function",
    "name": "Convert msg to http out",
    "func": "msg.payload = {\n    result: msg.payload,\n    status: msg.status\n};\nif(msg.html_attributions){\n\tmsg.payload.html_attributions = msg.html_attributions;\n}\nreturn msg;",
    "outputs": 1,
    "x": 1072,
    "y": 259,
    "z": "a37c852.f41b9f8",
    "wires": [
      [
        "41a8416f.3ee9"
      ]
    ]
  }
]
lostinthestory

Flow Info

created 2 years, 6 months ago

Node Types

Core
  • catch (x1)
  • function (x7)
  • http in (x3)
  • http response (x2)
Other

Tags

  • Google
  • Place
  • GooglePlaces
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option