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 notificationsheader link

Creating basic geofencing subscriptionsheader link

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 parametersheader link

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 parametersheader link

ParametersTypeDescriptionMandatory or Optional
deviceobjectThe device object previously created for the device we want to track.Mandatory
sinkstringThe recipient's HTTP endpoint, which is a web server configured to receive POST requests.Mandatory
typeslistA list of string values or EventType objects indicating the status type you want to check. Either area-entered or area-left.Mandatory
areaobjectContains the information of the defined geofencing area, for example the coordinates or the point of interest name of the area.Mandatory
poi_namestringName of the point of interest for a POI type geofencing area.Mandatory (for POI)
latitudefloatIndicates the north–south position of the location for a Circle type geofencing area.Mandatory (for Circle)
longitudefloatIndicates the east-west position of the location for a Circle type geofencing area.Mandatory (for Circle)
radiusintegerExpected accuracy in meters from center for a Circle type geofencing area.Mandatory (for Circle)
sink_credentialobjectAllows 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_timeobjectA 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_eventsintegerControls how many notifications you wish to receive, after which the subscription will expire.Optional
initial_eventbooleanIf set to true, a notification will be sent immediately after subscription if current situation reflects event request.Optional

Geofencing event typesheader link

Event typeTypeDescription
area-enteredobject/stringEventType.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-leftobject/stringEventType.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 typesheader link

ParametersTypeDescription
Plainobject/stringPlainCredential or "PLAIN". A plain credential as a combination of an identifier and a secret.
AccessTokenobject/stringAccessTokenCredential or "ACCESSTOKEN". An access token credential. An access token is a previously acquired token granting access to the target resource.

Receiving geofencing notificationsheader link

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 typeTypeDescription
area-enteredstringorg.camaraproject.geofencing-subscriptions.v0.area-entered - Notifications sent if the device enters into geofenced area.
area-leftstringorg.camaraproject.geofencing-subscriptions.v0.area-left - Notifications sent if the device leaves geofenced area.
subscription-endsstringorg.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 reasonsTypeDescription
NETWORK_TERMINATEDstringAPI server stopped sending notification.
SUBSCRIPTION_UNPROCESSABLEstringSubscription cannot be processed due to some reason, e.g. because the specified area cannot be managed.
SUBSCRIPTION_EXPIREDstringSubscription expire time (optionally set by the requester) has been reached.
SUBSCRIPTION_DELETEDstringSubscription was deleted by the requester.
MAX_EVENTS_REACHEDstringMaximum number of events (optionally set by the requester) has been reached.
ACCESS_TOKEN_EXPIREDstringAccess Token sinkCredential (optionally set by the requester) expiration time has been reached.

Notification-keyword valuesheader link

Notification-keyword valuesTypeDescription
idstringThe event identifier.
sourcestringIdentifies the source where the event happened. It contains the Network as Code API implementation and subscription ID.
timestringTime when the event occurred. Date and time are specified in ISO 8601 format, e.g.: "2025-08-20T21:01:02.345Z".
typestringValue 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.
specversionstringRepresents the specification version.
datacontenttypestringIt indicates the media type for the event payload encoding. It must be "application/json" in the context of CAMARA APIs.
dataobjectContains multiple subscription data, e.g. the subscription id and the geofencing area.

Managing geofencing subscriptionsheader link

Get all active subscriptionsheader link

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 IDheader link

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 subscriptionheader link

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