Skip to main content

Geofences

Geofences are virtual boundaries defined on a map that trigger events when devices enter or exit them. They're the foundation of location-based automation in SpatialFlow.

What is a Geofence?​

A geofence is a virtual perimeter around a real-world geographic area. When a device's location crosses this boundary, SpatialFlow detects the transition and can trigger automated actions through workflows.

Real-world examples:

  • A delivery zone around a restaurant that notifies when drivers enter
  • A restricted area that sends alerts when unauthorized devices cross the boundary
  • A retail store location that triggers marketing actions when customers arrive
  • A job site perimeter that logs worker entry and exit times

Geofence Types​

SpatialFlow supports polygon and circle geofences to match a variety of real-world boundaries.

Polygon Geofences​

Polygon geofences allow you to define custom-shaped boundaries using multiple vertices (points).

Use cases:

  • Irregularly shaped properties or facilities
  • Delivery zones that follow street patterns
  • Campus or industrial complex boundaries
  • Service areas that match neighborhood boundaries

Key characteristics:

  • Defined by 3 to 1,000 vertices (plan-dependent maximum)
  • More vertices = more precise boundaries
  • GeoJSON Polygon format with coordinate arrays
  • Automatically closed (first and last points connect)

Example polygon structure:

{
"type": "Polygon",
"coordinates": [
[
[-122.4194, 37.7749], // First vertex (lng, lat)
[-122.4184, 37.7749],
[-122.4184, 37.7739],
[-122.4194, 37.7739],
[-122.4194, 37.7749] // Last vertex (must match first)
]
]
}
Drawing Polygons

Use the SpatialFlow Dashboard's map interface to draw polygons visually. Click to place vertices, double-click to complete. The UI handles closing the polygon automatically.

Circle Geofences​

Circle geofences define a boundary using a center point and a radius in meters. They're ideal for simple, symmetrical zones.

Use cases:

  • Point-of-interest proximity alerts (e.g., within 500m of a store)
  • Simple job site perimeters
  • Delivery drop-off radius zones
  • Asset proximity monitoring

Key characteristics:

  • Defined by a center point (longitude, latitude) and radius in meters
  • Uses a custom Circle geometry type (not a standard GeoJSON type)
  • Rendered as a circle on the Dashboard map

Example circle structure:

{
"name": "Store Proximity Zone",
"geometry": {
"type": "Circle",
"center": [-74.006, 40.714],
"radius_meters": 500
}
}
Drawing Circles

Use the Dashboard's Draw circle tool to create circle geofences visually. Click a center point and drag to set the radius.

Key Properties​

Every geofence in SpatialFlow has these core properties:

Name (Required)​

  • Human-readable identifier
  • 1-100 characters
  • Example: "Downtown Delivery Zone"

Geometry (Required)​

  • GeoJSON Polygon, MultiPolygon, or Circle (custom type) defining the boundary
  • Coordinates in [longitude, latitude] format
  • SRID 4326 (WGS84) coordinate system
  • Validated on creation

Description (Optional)​

  • Detailed notes about the geofence
  • Up to 500 characters
  • Example: "Primary delivery area covering downtown district"

Metadata (Optional)​

  • Custom JSON object for storing additional data
  • Use for tagging, categorization, or application-specific data
  • Example:
{
"region": "north",
"priority": "high",
"cost_center": "12345"
}

Active Status​

  • Boolean flag to enable/disable the geofence
  • Inactive geofences don't trigger events
  • Useful for temporary disabling without deletion

Group (Optional)​

  • Organize related geofences into named groups
  • Group ID and group name for logical workspace
  • Query all geofences in a group via API

Creating Geofences​

Via API​

Create a polygon geofence using the REST API:

curl -X POST https://api.spatialflow.io/api/v1/geofences/ \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Downtown Office",
"description": "Main office building geofence",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-122.4194, 37.7749],
[-122.4184, 37.7749],
[-122.4184, 37.7739],
[-122.4194, 37.7739],
[-122.4194, 37.7749]
]
]
},
"metadata": {
"building": "headquarters",
"floor_count": 5
}
}'

Response:

{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Downtown Office",
"description": "Main office building geofence",
"geometry": {
"type": "Polygon",
"coordinates": [...]
},
"geometry_type": "Polygon",
"radius_meters": null,
"webhook_url": null,
"webhook_events": [],
"metadata": {
"building": "headquarters",
"floor_count": 5
},
"is_active": true,
"group_id": null,
"group_name": null,
"created_at": "2025-11-10T10:00:00Z",
"updated_at": "2025-11-10T10:00:00Z"
}

Via Dashboard​

The SpatialFlow dashboard provides a visual interface for geofence creation: draw the boundary on a map, type an address and set a buffer radius around it, or import many at once from a CSV file. See Geofences in the manager guides for the walkthrough.

Geofence Groups​

Groups help organize related geofences for easier management and querying.

Common grouping strategies:

  • By region: "West Coast Stores", "East Coast Warehouses"
  • By type: "Delivery Zones", "Restricted Areas", "Parking Lots"
  • By customer: "Client A Locations", "Client B Sites"
  • By project: "Q4 Campaign", "Winter Operations"

Creating grouped geofences:

{
"name": "Store #101",
"group_name": "Retail Locations",
"geometry": { ... }
}

Listing all groups:

curl https://api.spatialflow.io/api/v1/geofences/groups \
-H "X-API-KEY: YOUR_API_KEY"

Response:

{
"groups": [
{
"group_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"group_name": "Retail Locations",
"geofence_count": 47
}
],
"count": 1
}

Tags​

Tags are a lighter alternative to groups: a geofence can carry several of them, and a trigger can target every geofence with a given tag (target_mode: "tags"), including ones added later. Tag names are case-insensitive and scoped to the workspace; up to 20 tags per geofence, up to 50 characters each.

Pass tag names, not IDs, when creating or updating a geofence. A tag that doesn't exist yet in the workspace is created automatically:

{
"name": "Store #101",
"tags": ["retail", "west-coast"],
"geometry": { ... }
}

List every tag in the workspace, with how many geofences use each one:

curl https://api.spatialflow.io/api/v1/geofences/tags \
-H "X-API-KEY: YOUR_API_KEY"
{
"tags": [
{"id": "a1b2c3d4-...", "name": "retail", "normalized_name": "retail", "usage_count": 12}
],
"total": 1,
"truncated": false
}

Address-Source Geofences​

Instead of drawing a boundary, create a geofence from an address: SpatialFlow geocodes it, drops a point, and draws a circle of your chosen radius around it.

{
"name": "Downtown Depot",
"source": "address",
"address": "123 Main St, Springfield, IL",
"buffer_meters": 150
}

buffer_meters is 1 to 10,000. The response includes the geocoded point, the buffer_meters used, and source: "address"; source_metadata carries the geocoder's provenance (name, confidence, normalized address components).

Duplicate detection​

Creating an address-source geofence checks the workspace's active, non-archived geofences for a match: an exact normalized_address match, or any geofence within 50 meters of the new point. A match returns 409 Conflict with error_code: "GEOFENCE_DUPLICATE" and a matches array naming each conflicting geofence, with match_reason of "address" or "coordinate" and, for a coordinate match, the distance in meters. Pass "confirm_duplicate": true to create it anyway.

Building Footprints​

An address-source geofence starts as a circle. From the dashboard, you can replace that circle with the actual building's footprint, sourced from Overture Maps building data (source becomes "building", and source_id stores the Overture GERS id). The original buffer geometry is snapshotted first, so the geofence can be reverted back to it. This upgrade only applies to address-source geofences, and today it's a dashboard-only feature: it isn't part of the public API. See Use the building outline instead of a circle in the manager guides.

Schedules​

A geofence can be limited to certain days and hours, for example a checkpoint that only matters overnight. This is stored in metadata.schedule, not a top-level field:

{
"metadata": {
"schedule": {
"enabled": true,
"days": ["mon", "tue", "wed", "thu", "fri"],
"startTime": "09:00",
"endTime": "17:00",
"timezone": "America/New_York"
}
}
}

days are lowercase three-letter abbreviations. startTime and endTime are HH:MM; a start after the end wraps overnight. Outside the window, the geofence is invisible to entry/exit detection in both directions: nothing fires when the window opens or closes, except that a device already inside when the window opens is recorded as entering at that moment (it looked absent a moment before). A malformed schedule fails open (the geofence stays active) rather than silently going dark.

The test-point endpoints apply the window at the time of the request, so a geofence outside it reports is_inside: false there as well.

Archiving​

Archive hides a geofence from the default list and the map without deleting it. An archived geofence keeps its history (past workflow runs and reports still show it), is excluded from duplicate-detection matches, and still counts toward your plan's geofence limit. Enter, exit and dwell events still fire for it. expected_visit and geofence_occupancy workflows skip an archived geofence, and new ones can't be saved against one.

curl -X POST https://api.spatialflow.io/api/v1/geofences/{geofence_id}/archive \
-H "X-API-KEY: YOUR_API_KEY"

POST /geofences/{geofence_id}/unarchive restores it.

Best Practices​

Vertex Limits​

  • Minimum: 4 coordinate positions (3 unique vertices + closing point to form a triangle)
  • Maximum: 1,000 vertices, the same limit on every plan
  • Recommended: 4-50 vertices for most use cases
  • Performance tip: More vertices = longer processing time. Simplify complex boundaries when possible.

Coordinate Precision​

  • Use 6-8 decimal places for coordinates
  • Example: -122.419416, 37.774929
  • More precision doesn't improve accuracy beyond device GPS capabilities

Naming Conventions​

Use clear, descriptive names that include:

  • Location identifier: "Downtown SF Office"
  • Purpose: "Delivery Zone - Restaurant A"
  • Unique identifiers: "Store #101"

Good examples:

  • "SF HQ - Main Building"
  • "NYC Warehouse - Zone A"
  • "Customer Site - Acme Corp"

Avoid:

  • "Geofence 1"
  • "Test"
  • "asdf"

Metadata Usage​

Store application-specific data in metadata for:

  • Filtering: Query geofences by custom attributes
  • Display: Show additional info in your application
  • Integration: Pass context to downstream systems

Example metadata structure:

{
"metadata": {
"region": "west",
"type": "delivery_zone",
"contact_email": "ops@example.com",
"business_hours": "9am-5pm PST",
"priority": "high"
}
}

Performance Considerations​

  • Keep total geofence count reasonable (< 10,000 per workspace)
  • Use active/inactive status instead of deleting temporarily unused geofences
  • Group related geofences for easier bulk operations
  • Test complex polygons with the test point endpoint before production use

Testing Geofences​

Always test your geofences before connecting them to workflows:

curl -X POST https://api.spatialflow.io/api/v1/geofences/test-point \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"geometry": {
"type": "Point",
"coordinates": [-122.4194, 37.7749]
}
}'

Response shows which geofences contain the point:

{
"point": {
"type": "Point",
"coordinates": [-122.4194, 37.7749]
},
"results": [
{
"geofence_id": "123e4567-e89b-12d3-a456-426614174000",
"geofence_name": "Downtown Office",
"is_inside": true,
"distance_meters": 0
}
],
"inside_geofences": 1,
"total_geofences": 47
}

A point test sends no webhooks and creates no events, however often you repeat it. An API key needs the geofences:read permission and can't be read-only, because a read-only key can only make GET requests. To try a webhook or workflow end to end, simulate an event with POST /api/v1/geofences/{id}/test-event, which marks what it sends as a test.

Common Use Cases​

1. Delivery Zone Management​

Define service areas for delivery operations. Trigger notifications when drivers enter/exit zones, calculate dwell time, and optimize routing.

{
"name": "Pizza Delivery - Downtown",
"description": "30-minute delivery zone",
"metadata": {
"service_type": "delivery",
"max_delivery_time_minutes": 30,
"store_id": "store_123"
}
}

2. Restricted Area Monitoring​

Create security perimeters that alert when unauthorized devices enter. Useful for construction sites, private property, or secure facilities.

{
"name": "Construction Site - No Entry",
"description": "Active construction zone - authorized personnel only",
"metadata": {
"security_level": "restricted",
"contact": "security@example.com"
}
}

3. Store Locations​

Define retail locations for customer engagement campaigns. Trigger welcome messages, collect visit analytics, or activate location-based offers.

{
"name": "Retail Store #42 - Seattle",
"description": "Flagship store in downtown Seattle",
"metadata": {
"store_number": "042",
"manager": "Jane Smith",
"offers_enabled": true
}
}

4. Fleet Management​

Track vehicles entering depots, customer sites, or service areas. Automate check-in/check-out processes and monitor route adherence.

{
"name": "Depot - North Bay",
"description": "Primary vehicle depot",
"metadata": {
"depot_code": "NB001",
"capacity": 50,
"overnight_parking": true
}
}

Signals and Anomaly Detection​

Geofences also power SpatialFlow's anomaly detection signals, beyond entry and exit detection:

  • Dwell Detection: When a device stays inside a geofence beyond a configured time threshold, a dwell signal fires. Thresholds are set per-workflow, allowing different alert levels for the same geofence.
  • Policy Violations: Policies bind a geofence to time windows and device/role filters. When a device is inside a geofence during a restricted time window, a policy violation signal fires.

These signals feed into workflows just like geofence entry/exit events, enabling sophisticated automation like after-hours access alerts or extended-stay notifications.

See Signals for the full list of signal types and how they work.

Coordinate System​

SpatialFlow uses EPSG:4326 (WGS84), the same coordinate system used by GPS devices and most mapping APIs.

Format: [longitude, latitude]

  • Longitude: -180 to 180 (east-west)
  • Latitude: -90 to 90 (north-south)
Common Mistake

Note the order: longitude first, then latitude. This is the GeoJSON standard but opposite of how coordinates are often spoken (lat, lng).

Correct: [-122.4194, 37.7749] (lng, lat) Incorrect: [37.7749, -122.4194] (lat, lng)

Validation​

SpatialFlow validates all geofences on creation and update:

Validation rules:

  • Geometry must be valid GeoJSON
  • Polygons must be closed (first and last points match)
  • Coordinates must be within valid ranges
  • Exterior ring must have at least 4 coordinate positions (3 unique vertices + closing point)
  • Vertex count up to 1,000
  • No self-intersecting polygons
  • Area up to 1,000 km² (10,000 km² on the enterprise plan). A circle's radius is capped separately, at 100 km

Common validation errors:

  • Polygon must be closed: First and last coordinates don't match
  • Invalid coordinates: Longitude or latitude out of range
  • Too many vertices: Exceeded the 1,000-vertex limit
  • Self-intersecting polygon: Polygon edges cross each other
  • Polygon area too large. Maximum 1000 square kilometers allowed.: Exceeded the area cap

Next Steps​

Now that you understand geofences, explore related features:

  • Quick Start Guide - Create your first geofence in 5 minutes
  • Geofences - Draw, import and manage geofences from the dashboard
  • Workflows - Connect geofences to automated actions
  • Webhooks - Receive real-time geofence events
  • Signals: Dwell detection and policy violations powered by geofences
  • API Reference - Complete API documentation

API Endpoints​

Key geofence endpoints:

  • POST /api/v1/geofences/ - Create a geofence (draw or address source)
  • GET /api/v1/geofences - List all geofences
  • GET /api/v1/geofences/{id} - Get a specific geofence
  • PUT /api/v1/geofences/{id} - Update a geofence
  • DELETE /api/v1/geofences/{id} - Delete a geofence
  • POST /api/v1/geofences/{id}/archive / POST /api/v1/geofences/{id}/unarchive - Archive or restore a geofence
  • POST /api/v1/geofences/test-point - Test a point against all geofences; sends no webhooks
  • POST /api/v1/geofences/{id}/test-event - Simulate an enter or exit event, marked as a test
  • GET /api/v1/geofences/groups - List all geofence groups
  • GET /api/v1/geofences/groups/{group_id}/geofences - Get geofences in a group
  • GET /api/v1/geofences/tags - List workspace tags

See the API Reference for complete details and examples.