Table of Contents
Introduction
The ArcGIS API for Python is a powerful Python library that allows users to interact with and automate tasks in ArcGIS Online (or Portal). The API is excellent for programmatically creating, maintaining, and updating components of ArcGIS Online along with performing analysis tasks. In this blog post we will focus on creating a new Hosted Feature Service and adding a Feature Layer. We will see the minimum viable Feature Layer definition required to add a new Feature Layer to an existing Feature Service.
This blog post is also available on the Esri Community site.
Unlock the full potential of ArcGIS Online by mastering the art of efficient Content Management with the ArcGIS API for Python. In this comprehensive course, you will embark on a journey to streamline your geospatial workflows, enhance data organization, and maximize the impact of your ArcGIS Online platform.
Geospatial Professionals, GIS Analysts, Data Managers, and enthusiasts will discover the power of automation and script-based operations to efficiently manage content in ArcGIS Online. Throughout this course, you will gain practical, hands-on experience in leveraging the ArcGIS API for Python to perform a wide range of content management tasks with ease.
arcgis modules
The API provides access to your organisations ArcGIS Online via the GIS class in the gis module. This GIS class is the gateway to ArcGIS Online. We also need to import the FeatureLayerCollectionclass. A FeatureLayerCollection object represents a Feature Service in ArcGIS Online.
## provides access to ArcGIS Online
from arcgis.gis import GIS
## represents a Feature Service
from arcgis.features import FeatureLayerCollection
Accessing ArcGIS Online
GIS
class. There are a handful of ways to achieve access, if you are logged into your ArcGIS Online in ArcGIS Pro you can simply use "home"
, otherwise, another common way is to provide the ArcGIS Online URL, followed by your username and password.
## Access AGOL
agol = GIS("home")
## Access AGOL
agol = GIS(
url = "https://your_organisation.maps.arcgis.com/",
username = "Your_Username",
password = "Your_Password"
)
The Name/Type of the Feature Service to Create
I’m sure you already have a name for the Feature Service in mind. This name is what gets embedded in the URL for the Feature Service, it is locked-in once the Feature Service is created. This is also the title of the Feature Service, which you see in the Contents of ArcGIS Online, which you can alter at any time after the Feature Service is created.
service_name = "API_CREATED_SERVICE"
service_type = "featureService"
Create the Feature Service
We utilise the ContentManager create_service() method to create the new Hosted Feature Service. This method will return an Item object representing our newly created Feature Service content item.
empty_service_item = agol.content.create_service(
name = service_name,
service_type = service_type,
)
The Feature Layer Definition (Dictionary)
The aim in this blog is to look at the minimum Feature Layer definition required and we achieve that below with the exception of adding in some extra fields just to see the different field definitions. One of the main requirements is the indexes and setting the unique field for the Feature Layer.
fl_definition = {
"type" : "Feature Layer",
"name" : "API_CREATED_POINT_LAYER",
"geometryType" : "esriGeometryPoint", # esriGeometryPolygon, esriGeometryPolyline
"fields" : [
{
"name" : "OBJECTID",
"type" : "esriFieldTypeOID",
"actualType" : "int",
"alias" : "OBJECTID",
"sqlType" : "sqlTypeInteger",
"nullable" : False,
"editable" : False
},{
"name": "INTEGER_FIELD",
"type": "esriFieldTypeInteger",
"actualType": "int",
"alias": "Integer Field",
"sqlType": "sqlTypeInteger",
"nullable": True,
"editable": True
},{
"name": "STRING_FIELD",
"type": "esriFieldTypeString",
"actualType": "nvarchar",
"alias": "String Field",
"sqlType": "sqlTypeNVarchar",
"length": 25,
"nullable": True,
"editable": True
},
{
"name": "DOUBLE_FIELD",
"type": "esriFieldTypeDouble",
"actualType": "float",
"alias": "Decimal Field",
"sqlType": "sqlTypeFloat",
"nullable": True,
"editable": True
},
{
"name": "DATE_FIELD",
"type": "esriFieldTypeDate",
"alias": "Date Field",
"sqlType": "sqlTypeOther",
"nullable": True,
"editable": True
}
],
"indexes" : [ # required index for Primary Key
{
"name" : "PK_IDX",
"fields" : "OBJECTID",
"isAscending" : True,
"isUnique" : True,
"description" : "clustered, unique, primary key"
}
],
"objectIdField" : "OBJECTID",
"uniqueField" : { # a unique field is required
"name" : "OBJECTID",
"isSystemMaintained" : True
}
}
You can add other definition properties to the dictionary. We could add in the symbology (drawingInfo) definition for the Feature Layer, the Popup (popupInfo) definition, Label (labelingInfo) definitions, and other properties such as id (not required as ArcGIS Online will handle this for you), and description amongst others.
Add the Feature Layer Definition to the Feature Service
The final hurdle, adding the Feature Layer definition to the Feature Service. We first create a FeatureLayerCollection object from the Item object. A FeatureLayerCollection represents the Feature Service.
## re-get the updated item object
add_lyr_item = agol.content.get(add_lyr_item_id)
## get the layer of interest
fl = [lyr for lyr in add_lyr_item.layers if lyr.properties.name == lyr_name][0]
## populate with data
fl.edit_features(adds=fs.features)
The Output
The create Feature Service content item.

The service item homepage.

The fields created.

Geospatial Professionals, GIS Analysts, and enthusiasts will discover the power of automation and script-based operations to efficiently interact and update WebMaps in ArcGIS Online. Throughout this course, you will gain practical, hands-on experience in leveraging the ArcGIS API for Python to perform a wide range of WebMap tasks with ease.
We will dissect WebMaps for all that they are and by the end of this course you will be comfortable with manipulating the JSON, which is the behind the scenes configuration of a WebMap, to produce scripts for workflows where there is currently no API Python method, such as grouping layers.
All the code in one place
You can find the entire code workflow below with links to important components in the documentation that were used.
from arcgis.gis import GIS
from arcgis.features import FeatureLayerCollection
## https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#gis
## https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#contentmanager
## https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#arcgis.gis.ContentManager.create_empty_service
## https://developers.arcgis.com/python/latest/api-reference/arcgis.features.toc.html#featurelayercollection
## https://developers.arcgis.com/python/latest/api-reference/arcgis.features.managers.html#featurelayercollectionmanager
## https://developers.arcgis.com/python/latest/api-reference/arcgis.features.managers.html#arcgis.features.managers.FeatureLayerCollectionManager.add_to_definition
## https://developers.arcgis.com/python/latest/api-reference/arcgis.features.toc.html#featurelayer
## Access AGOL
agol = GIS("home")
## the service name and type to create
service_name = "API_CREATED_SERVICE"
service_type = "featureService"
## create the feature service
empty_service_item = agol.content.create_service(
name = service_name,
service_type = service_type,
)
fl_definition = {
"type" : "Feature Layer",
"name" : "API_CREATED_POINT_LAYER",
"geometryType" : "esriGeometryPoint", # esriGeometryPolygon, esriGeometryPolyline
"fields" : [
{
"name" : "OBJECTID",
"type" : "esriFieldTypeOID",
"actualType" : "int",
"alias" : "OBJECTID",
"sqlType" : "sqlTypeInteger",
"nullable" : False,
"editable" : False
},{
"name": "INTEGER_FIELD",
"type": "esriFieldTypeInteger",
"actualType": "int",
"alias": "Integer Field",
"sqlType": "sqlTypeInteger",
"nullable": True,
"editable": True
},{
"name": "STRING_FIELD",
"type": "esriFieldTypeString",
"actualType": "nvarchar",
"alias": "String Field",
"sqlType": "sqlTypeNVarchar",
"length": 25,
"nullable": True,
"editable": True
},
{
"name": "DOUBLE_FIELD",
"type": "esriFieldTypeDouble",
"actualType": "float",
"alias": "Decimal Field",
"sqlType": "sqlTypeFloat",
"nullable": True,
"editable": True
},
{
"name": "DATE_FIELD",
"type": "esriFieldTypeDate",
"alias": "Date Field",
"sqlType": "sqlTypeOther",
"nullable": True,
"editable": True
}
],
"indexes" : [ # required index for Primary Key
{
"name" : "PK_IDX",
"fields" : "OBJECTID",
"isAscending" : True,
"isUnique" : True,
"description" : "clustered, unique, primary key"
}
],
"objectIdField" : "OBJECTID",
"uniqueField" : { # a unique field is required
"name" : "OBJECTID",
"isSystemMaintained" : True
}
}
## Create a FeatureLayerCollection object from the Item object
flc = FeatureLayerCollection.fromitem(empty_service_item)
## Update the JSON definition of the Service to include the layer
flc.manager.add_to_definition({"layers": [fl_definition]})