QGIS get data from API

Posted by John Liu on Sunday, February 4, 2024

To retrieve data via API call in QGIS, we can utilise Python code to make the API call.

Launch QGIS, open Plugins -> Python Console. In Python Console, click Show Editor icon to open editor. In editor window, make new script or open the Python script and execute the Python script. Following is an example Python script to make API call.

##If keyring is not installed, run the following in QGIS Python console to install keyring. Keyring requires Python 3.8+
#import pip
#pip.main(['install','keyring'])
#
##After installed keyring, using following DOS comand to create secure credential entry. KeyName value is the API key name, Password is the API key
#keyring --help
#keyring set MDSAPI KeyName
#keyring set MDSAPI Password

#IMPORT LIBRARY
import pandas as pd
import urllib.request
import urllib.parse as urlparse
from urllib.parse import urlencode
import json
import ssl

from qgis.core import QgsProject,QgsVectorLayer,QgsField,QgsGeometry,QgsPointXY,QgsFeature
from qgis.PyQt.QtCore import QVariant

import keyring

#get API key name and key securely stored in keyring
APIKeyName = keyring.get_password("MDSAPI","KeyName")   #this is the API credentials stored in Keyring
APIKey = keyring.get_password("MDSAPI","Password")  #this is the API credentials stored in Keyring

#from shapely.geometry import Point
#from qgis.core import QgsVectorLayer, QgsField, QgsFeature, QgsGeometry, QgsMapLayerRegistry

#HEADER
ssl._create_default_https_context = ssl._create_unverified_context
opener = urllib.request.build_opener()
#opener.addheaders = [('User-agent','Mozilla/5.0')]

opener.addheaders = [(APIKeyName, APIKey)]  #This line is needed only if your API requires API key in the header
#for example: key name is Authorization and key is 12345
#opener.addheaders = [('Authorization','12345')]

#SEND REQUEST, READ RESPONSE AND LOAD AS JSON
#url_str='http://localhost:5002/api/tblLIBPerson?$select=Code,Description&$filter=Code eq \'ago\''
#url_str='http://localhost:5002/api/tblDHColl?$first=20&$select=DataSet,Hole_ID,LL_Lat,LL_Long&$filter=DataSet eq \'AU AND BM CAN\''
url_str = 'https://mytestapi1.azure-api.net/mds/api/tblDHColl?$first=20&$select=DataSet,Hole_ID,LL_Lat,LL_Long&$filter=DataSet eq \'AU AND BM CAN\''
url_str=url_str.replace(" ","%20")  #Spaces are not allowed in URL, replacing whitespace with %20
#print(url_str)
fp = opener.open(url_str)
mybyte = fp.read()
mystr = mybyte.decode("utf8")
js_str = json.loads(mystr)
fp.close()

#CONVERT TO PANDAS DATAFRAME
df=pd.DataFrame.from_dict(js_str['value'],orient="columns")
df=df.fillna('No Data') #replace NAN with No Data
#print(df)
#print(df.head())

#following lines add the retrieved data into a QGIS memory layer
# define name for the temp meory layer
my_memory_layer_name = 'My Test Layer'

# Get the existing layer my_memory_layer_name if it exists
existing_my_memory_layer = QgsProject.instance().mapLayersByName(my_memory_layer_name)

# Remove the existing layer from the project
if existing_my_memory_layer:
    QgsProject.instance().removeMapLayer(existing_my_memory_layer[0].id())
    
# Create a memory layer
layer = QgsVectorLayer('Point?crs=EPSG:4326', my_memory_layer_name, 'memory')

# Define fields for the layer
fields = []
fields.append(QgsField('DataSet', QVariant.String, len=50))
fields.append(QgsField('Hole_ID', QVariant.String, len=50))
layer.dataProvider().addAttributes(fields)
layer.updateFields()

# Add features to the layer
features = []
for index, row in df.iterrows():
    point = QgsGeometry.fromPointXY(QgsPointXY(row['LL_Long'], row['LL_Lat']))
    feature = QgsFeature()
    feature.setGeometry(point)
    feature.setAttributes([row['DataSet'],row['Hole_ID']])
    features.append(feature)

layer.dataProvider().addFeatures(features)

# Add the layer to the map
QgsProject.instance().addMapLayer(layer)

To securely store the API crendential, we use Keyring. Keyring required Python 3.8+,

Install Keyring on your OS

python -m pip install keyring

After installed keyring, using following DOS comand to create secure key entry. KeyName value is the API key name, Password is the API key

REM defin MDSAPI as your service and KeyName as username in Keyring, when prompt for password, enter your API key name
keyring set MDSAPI KeyName
REM define Password as username under the same MDSAPI service in Keyring, when prompt for password, enter your API key
keyring set MDSAPI Password

You also need to install Keyring in the QGIS Python Console before you can retrieve the credentials from Keyring, run the following Python script in the Console. If not, you may receive “ModuleNotFoundError: No module named ‘keyring’” error when run your Python script.

import pip
pip.main(['install','keyring'])