Webhook-triggered events. Mobile app sends location updates → Fencemaker checks territories → fires webhook on entry/exit.
Free tier: 1,000 location updates/day. Growth plan covers 35,000/day for real-time fleet tracking.
Three ways to create territories:
• Dashboard UI: Draw polygons at fencemaker.app/dashboard/fences
• Import GeoJSON: Upload from Google Maps, Mapbox Studio, QGIS
• API: POST /api/v1/territories with GeoJSON body (for bulk/programmatic creation)
Then configure webhook endpoint at fencemaker.app/dashboard/webhooks.
Must be public HTTPS — test locally with ngrok first.
Your driver/field app sends updates every 30–60 seconds:
POST /api/v1/track with { "device_id": "driver_42", "lat": 12.9716, "lon": 77.5946 }
How to get GPS coordinates:
• Native iOS: Core Location framework (requestWhenInUseAuthorization → startUpdatingLocation)
• Native Android: FusedLocationProviderClient (requestLocationUpdates)
• React Native: react-native-geolocation-service or expo-location
• Flutter: geolocator package
Fencemaker checks each location against all your territories.
Webhook fires only on state changes (outside → inside, or inside → outside).
No polling needed — you're notified instantly on entry/exit.
Your endpoint gets POST with event type ("entered"/"exited"), territory_id, territory_name, device_id. Send SMS, update status, log event.
// Your webhook endpoint receives POST from Fencemaker:
// POST https://yourapi.com/webhooks/geofence
// {
// "event": "entered",
// "territory_id": "uuid",
// "territory_code": "ZONE-A",
// "territory_name": "East Austin",
// "device_id": "driver_42",
// "timestamp": "2026-05-10T14:32:00Z",
// "lat": 12.9716, "lon": 77.5946
// }
app.post('/webhooks/geofence', async (req, res) => {
const { event, territory_id, device_id, lat, lon } = req.body;
if (event === 'entered') {
// Driver entered customer neighborhood
const order = await findOrderByTerritory(territory_id);
// Send customer notification
await sendSMS(order.customer_phone,
'Your delivery is 10 minutes away!'
);
// Update tracking status
await updateStatus(order.id, 'out_for_delivery');
}
if (event === 'exited') {
// Package left warehouse zone
await logEvent('package_dispatched', { device_id, territory_id });
}
res.sendStatus(200); // Always respond 200 within 5 seconds
});Webhooks require a public HTTPS endpoint (not http://localhost). Test locally with ngrok first. Fencemaker expects a 200 response within 5 seconds or it retries. Don't block the webhook handler with slow downstream calls — queue work asynchronously. Webhook event values are "entered" and "exited" (not "entry"/"exit").