Geofencing
The geofencing functionality allows applications to track when a given device enters or leaves a location based on the coordinates and radius or a named point of interest that have been provided.
Geofencing works off the same location information as location retrieval and verification. This means that in some cases where the area is defined as a circle, accuracy is on cell tower level, so specifying too small of an area may result in incomplete or inaccurate results and in some countries or on some networks the minimum radius may be regulated. Therefore, this functionality is best applied to situations where a course-grained location notification is desired.
Subscribing to geofencing notifications
Creating basic geofencing subscriptions
The snippet below allows you to subscribe a specific device to geofencing.
It creates a geofenced circle of 2000 meters centered on latitude
47.48627616952785 and longitude 19.07915612501993 and will send a
notification to https://example.com/notify if the device enters this
region.
import network_as_code as nac
from network_as_code.models.geofencing import EventType, Circle, Center
client = nac.NetworkAsCodeClient(
token="<your-application-key-here>"
)
device = client.devices.get(phone_number="+3637123456")
subscription = client.geofencing.subscribe(
device=device,
sink="https://example.com/notify",
types=[EventType.AREA_LEFT],
area=Circle(center=Center(latitude=47.48627616952785, longitude=19.07915612501993), radius=2000)
)You can alternatively subscribe a specific device to geofencing using an area defined by a point of interest. This can be for example an industrial zone or shopping district provided by its name as a simple string.
import network_as_code as nac
from network_as_code.models.geofencing import EventType, POI
client = nac.NetworkAsCodeClient(
token="<your-application-key-here>"
)
device = client.devices.get(phone_number="+3637123456")
subscription = client.geofencing.subscribe(
device=device,
sink="https://example.com/notify",
types=[EventType.AREA_LEFT],
area=POI(poi_name="StatueOfLiberty")
)Creating geofencing subscriptions with optional parameters
It's also possible to pass in optional parameters to the subscription:
import network_as_code as nac
from datetime import datetime, timedelta, timezone
from network_as_code.models.geofencing import PlainCredential, EventType, Circle, Center
client = nac.NetworkAsCodeClient(
token="<your-application-key-here>"
)
device = client.devices.get(phone_number="+3637123456")
subscription = client.geofencing.subscribe(
device=device,
sink="https://example.com/notify",
types=[EventType.AREA_LEFT],
area=Circle(center=Center(latitude=47.48627616952785, longitude=19.07915612501993), radius=2000),
sink_credential=PlainCredential(identifier="client-id",secret="client-secret"),
subscription_expire_time=datetime.now(timezone.utc) + timedelta(days=1),
subscription_max_events=1,
initial_event=True
)Geofencing parameters
| Parameters | Type | Description | Mandatory or Optional |
|---|---|---|---|
device | object | The device object previously created for the device we want to track. | Mandatory |
sink | string | The recipient's HTTP endpoint, which is a web server configured to receive POST requests. | Mandatory |
types | list | A list of string values or EventType objects indicating the status type you want to check. Either area-entered or area-left. | Mandatory |
area | object | Contains the information of the defined geofencing area, for example the coordinates or the point of interest name of the area. | Mandatory |
poi_name | string | Name of the point of interest for a POI type geofencing area. | Mandatory (for POI) |
latitude | float | Indicates the north–south position of the location for a Circle type geofencing area. | Mandatory (for Circle) |
longitude | float | Indicates the east-west position of the location for a Circle type geofencing area. | Mandatory (for Circle) |
radius | integer | Expected accuracy in meters from center for a Circle type geofencing area. | Mandatory (for Circle) |
sink_credential | object | Allows specifying how the notification is authenticated and the authentication information. For example sink_credential=PlainCredential(identifier="client-id",secret="client-secret"). Credential type can be either "PLAIN" or "ACCESSTOKEN". | Optional |
subscription_expire_time | object | A datetime object, that sets the date for when the subscription should be automatically expired. If no expiration time has been provided, the subscription expiration value will be None. | Optional |
subscription_max_events | integer | Controls how many notifications you wish to receive, after which the subscription will expire. | Optional |
initial_event | boolean | If set to true, a notification will be sent immediately after subscription if current situation reflects event request. | Optional |
Geofencing event types
| Event type | Type | Description |
|---|---|---|
area-entered | object/string | EventType.AREA_ENTERED or org.camaraproject.geofencing-subscriptions.v0.area-entered - Used for checking if the device is connected to the network for data usage. |
area-left | object/string | EventType.AREA_LEFT or org.camaraproject.geofencing-subscriptions.v0.area-left - Used for checking if the device is connected to the network for SMS usage. |
Credential types
| Parameters | Type | Description |
|---|---|---|
Plain | object/string | PlainCredential or "PLAIN". A plain credential as a combination of an identifier and a secret. |
AccessToken | object/string | AccessTokenCredential or "ACCESSTOKEN". An access token credential. An access token is a previously acquired token granting access to the target resource. |
Receiving geofencing notifications
Geofencing notifications are delivered using CloudEvents
to the event sink specified in the subscription. Network as Code currently
only supports delivery via HTTP, which means that notifications will be sent
as POST requests to the sink URL and will contain the event information
as a JSON payload.
The notifications will also come with identifying information specified by the sink credentials.
There are three types of geofencing notifications that you may receive:
| Notification type | Type | Description |
|---|---|---|
area-entered | string | org.camaraproject.geofencing-subscriptions.v0.area-entered - Notifications sent if the device enters into geofenced area. |
area-left | string | org.camaraproject.geofencing-subscriptions.v0.area-left - Notifications sent if the device leaves geofenced area. |
subscription-ends | string | org.camaraproject.geofencing-subscriptions.v0.subscription-ends - Notifications sent if geofencing subscription has been terminated. |
Area entry notification will have a request body of the following schema:
{
"id": "event-id-random-123",
"source": "/whatever-api/v1/subscriptions/123",
"time": "2025-07-01T14:15:16.789Z",
"specversion" : "1.0",
"type": "org.camaraproject.geofencing-subscriptions.v0.area-entered",
"datacontenttype" : "application/json",
"data": {
"subscriptionId": "subscriptionId-123",
"device": {...},
"area": {...}
}
}
Area left notification schema is:
{
"id": "event-id-random-123",
"source": "/whatever-api/v1/subscriptions/123",
"time": "2025-07-01T14:15:16.789Z",
"specversion" : "1.0",
"type": "org.camaraproject.geofencing-subscriptions.v0.area-left",
"datacontenttype" : "application/json",
"data": {
"subscriptionId": "subscriptionId-123",
"device": {...},
"area": {...}
}
}
And subscription termination will result in:
{
"id": "event-id-random-123",
"source": "/whatever-api/v1/subscriptions/123",
"time": "2025-07-01T14:15:16.789Z",
"specversion" : "1.0",
"type": "org.camaraproject.geofencing-subscriptions.v0.subscription-ends",
"datacontenttype" : "application/json",
"data": {
"subscriptionId": "subscriptionId-123",
"device": {...},
"area": {...}
"terminationReason": "..."
}
}
The termination reason may be one of the following:
| Termination reasons | Type | Description |
|---|---|---|
NETWORK_TERMINATED | string | API server stopped sending notification. |
SUBSCRIPTION_UNPROCESSABLE | string | Subscription cannot be processed due to some reason, e.g. because the specified area cannot be managed. |
SUBSCRIPTION_EXPIRED | string | Subscription expire time (optionally set by the requester) has been reached. |
SUBSCRIPTION_DELETED | string | Subscription was deleted by the requester. |
MAX_EVENTS_REACHED | string | Maximum number of events (optionally set by the requester) has been reached. |
ACCESS_TOKEN_EXPIRED | string | Access Token sinkCredential (optionally set by the requester) expiration time has been reached. |
Notification-keyword values
| Notification-keyword values | Type | Description |
|---|---|---|
id | string | The event identifier. |
source | string | Identifies the source where the event happened. It contains the Network as Code API implementation and subscription ID. |
time | string | Time when the event occurred. Date and time are specified in ISO 8601 format, e.g.: "2025-08-20T21:01:02.345Z". |
type | string | Value returned by the API with different statuses. Can be area-entered, area-left or subscription-ends. For example org.camaraproject.geofencing-subscriptions.v0.area-left. |
specversion | string | Represents the specification version. |
datacontenttype | string | It indicates the media type for the event payload encoding. It must be "application/json" in the context of CAMARA APIs. |
data | object | Contains multiple subscription data, e.g. the subscription id and the geofencing area. |
Managing geofencing subscriptions
Get all active subscriptions
All of the currently active Geofencing subscriptions can be fetched using the get-all functionality. This will return a list containing the details of each subscription that hasn't yet been terminated.
import network_as_code as nac
client = nac.NetworkAsCodeClient(
token="<your-application-key-here>"
)
subscriptions = client.geofencing.get_all()Get subscription by ID
Geofencing subscriptions can also be fetched by subscription ID, if you already know it. This will just return the single subscription with that ID, assuming that it has not been terminated.
import network_as_code as nac
from network_as_code.models.geofencing import EventType, POI
client = nac.NetworkAsCodeClient(
token="<your-application-key-here>"
)
device = client.devices.get(phone_number="+3637123456")
subscription = client.geofencing.subscribe(
device=device,
sink="https://example.com/notify",
types=[EventType.AREA_ENTERED],
area=POI(poi_name="StatueOfLiberty")
)
subscription_id = subscription.event_subscription_id
same_subscription = client.geofencing.get(subscription_id)Delete subscription
Subscriptions can be manually terminated by deleting them. This is done by calling the delete method or endpoint.
import network_as_code as nac
from network_as_code.models.geofencing import EventType, Circle, Center
client = nac.NetworkAsCodeClient(
token="<your-application-key-here>"
)
device = client.devices.get(phone_number="+3637123456")
subscription = client.geofencing.subscribe(
device=device,
sink="https://example.com/notify",
types=[EventType.AREA_ENTERED],
area=Circle(center=Center(latitude=47.48627616952785, longitude=19.07915612501993), radius=2000)
)
subscription.delete()Last updated January 22, 2026