# Keep Connected-App Zones in Sync With Fleetr Let Dispatchr create, reshape and delete zones in Fleetr, and receive a signed event each time a vehicle enters or leaves one. Last updated: . Dispatchr owns its zones. It sends each one to Fleetr, Fleetr hands the area to its tracking server, and the tracking server watches every vehicle in the account against it. Crossings come back to Dispatchr through [event forwarding](/docs/event-forwarding). Fleetr also sends its usual geofence alerts for these zones, so fleet managers keep the push, SMS and email notifications they have set up. ## Before You Start - Create an account API token under **Account → Integrations → API access** (see [API integration](/docs/api-integration)). Only an account API token can manage zones. A person's login token is refused with `integration_token_required`. - The account's plan must include geofencing, and the account must have full subscription access. Otherwise Fleetr returns **403** `feature_not_in_plan` or **402**. - Send three headers on every request: `Authorization: Bearer YOUR_ACCOUNT_API_TOKEN`, `X-Account-ID` with the numeric id of the token's own account, and `X-Vertical: dispatchr`. There is no fallback to a default account. - You can send up to 60 requests a minute per token. Beyond that Fleetr returns **429**; wait and retry. ## Create or Update a Zone `POST /api/integrations/geofences` creates a zone, or updates it when the account already has one with the same `external_ref`. Retries are safe: they never create a second zone. ```http POST /api/integrations/geofences HTTP/1.1 Host: fleetr.co.ke Authorization: Bearer YOUR_ACCOUNT_API_TOKEN Accept: application/json Content-Type: application/json X-Account-ID: 123 X-Vertical: dispatchr {"name": "Westlands depot", "type": "circle", "center": {"lat": -1.2635, "lng": 36.8031}, "radius_m": 250, "external_ref": "zone-41"} ``` A polygon sends `points` instead of `center` and `radius_m`. Each point is `[lat, lng]`, latitude first: ```json {"name": "Industrial Area yard", "type": "polygon", "points": [[-1.3061, 36.8453], [-1.3061, 36.8502], [-1.3103, 36.8502], [-1.3103, 36.8453]], "external_ref": "zone-42"} ``` | Field | Rules | |---|---| | `name` | Required, up to 255 characters. Spaces are trimmed and repeated spaces collapsed. | | `type` | `circle` or `polygon`. | | `center` | Circles only: `{"lat", "lng"}`, latitude −90 to 90 and longitude −180 to 180. | | `radius_m` | Circles only: 10 to 50,000 metres. | | `points` | Polygons only: 3 to 100 distinct `[lat, lng]` vertices. A closing point equal to the first is accepted and dropped. The points must enclose an area and the edges must not cross. | | `external_ref` | Required on create: your own zone id, using letters, digits, `.`, `_`, `:` or `-` (up to 191 characters, starting with a letter or digit). | Coordinates are stored to 6 decimal places, about 10 cm. Any other field is refused with **422**, so a typo is reported rather than ignored. The response is **201** for a new zone and **200** when an existing zone was updated: ```json {"id": 5120, "external_ref": "zone-41", "name": "Westlands depot", "type": "circle", "vehicle_count": 18} ``` Store `id`: it is used for updates and deletes, and it is the `geofence_id` in crossing events. ## Change or Delete a Zone `PUT /api/integrations/geofences/{id}` replaces the zone's name and shape. Send the same body as on create. `external_ref` may be left out; if you send it, it must match the stored value, because it cannot be changed. The response has the same shape as a create. `DELETE /api/integrations/geofences/{id}` removes the zone, and it stops alerting straight away. Deleting a zone that is already deleted returns the same **200** body, so a retried delete is safe: ```json {"id": 5120, "external_ref": "zone-41", "deleted": true} ``` Crossing history is kept. If you later create a zone with the same `external_ref`, it becomes a new geofence with a new `id`. ## Which Vehicles a Zone Watches A zone watches **every vehicle in the Fleetr account**, the same vehicles the token sees through `GET /api/vehicles`. Vehicles added to the account later, or fitted with a tracker later, are added within the hour. A vehicle moved to another account stops being watched for this one. `vehicle_count` in the response shows how many vehicles the zone currently watches. ## Writes Reach the Tracker Straight Away Each create, update and delete is sent to Fleetr's tracking server in the same request, so a new or reshaped zone starts alerting immediately. You don't have to wait for the hourly sync. If the tracking server can't be reached, Fleetr saves nothing and returns **503** `tracking_unavailable`. Retry later with the same body. ## How Zones Appear in Fleetr Zones created through this API carry a **From Dispatchr** badge in the geofence list and on the vehicle's geofence tab. They are **read-only in Fleetr**: the edit, pause and delete buttons are hidden, and schedules can't be added or removed, because Dispatchr is the source of truth and its next sync would undo a Fleetr edit. A fleet manager can still copy a zone; the copy belongs to Fleetr and can be edited. The API can only change zones that Dispatchr owns on the token's account. A geofence on another account returns **404**. A geofence drawn in Fleetr, or owned by another app, returns **403** `not_integration_managed` and is left unchanged. ## Receive Entries and Exits Under **Account → Integrations → Event forwarding**, select **Geofence entered** (`geofence.enter`) and **Geofence exited** (`geofence.exit`) on the Dispatchr endpoint. Each crossing of each geofence is delivered once, signed like every other forwarded event. Match your zones on `geofence_external_ref`: ```json { "event_id": "1f0b6d1e-6c38-4e0f-9a52-0d1d7f3c5a10", "type": "geofence.enter", "version": 1, "occurred_at": "2026-10-23T07:15:00+00:00", "account_id": 123, "data": { "vehicle_id": 31, "vehicle_identification": "KDA 123A", "device_id": 77, "event_name": "geofenceEnter", "value": "Westlands depot", "lat": -1.2921, "lng": 36.8219, "bearing": 90, "duration": null, "speed_kmh": 19, "geofence_id": 5120, "geofence_name": "Westlands depot", "geofence_external_ref": "zone-41", "geofence_source": "dispatchr", "within_schedule": true } } ``` `occurred_at` is the GPS time of the crossing. Geofences drawn in Fleetr are delivered too, with `geofence_external_ref` and `geofence_source` set to `null`. When two geofences overlap, a vehicle crossing both on one GPS fix produces one event for each. Deduplicate on `event_id` and order by `occurred_at`. ## Errors | Status | Meaning | |---|---| | 401 | Missing or invalid token. | | 402 | The account does not have full subscription access. | | 403 | Not an account API token, not a member of `X-Account-ID`, geofencing not in the plan, or a geofence this app does not own. The body's `error` names which. | | 404 | No geofence with that id on the account. | | 409 | Another request is saving the same zone. Retry. | | 422 | Missing headers, an unknown field, or an invalid shape. The body lists each field. | | 429 | More than 60 requests a minute. | | 503 | The tracking server did not accept the zone. Nothing changed; retry. | The full schema is in the [interactive API reference](https://fleetr.co.ke/api/docs) under **Integration Geofences**. ## Related Guides - [API integration](/docs/api-integration) - [Event forwarding and webhooks](/docs/event-forwarding) - [Create and manage geofences](/docs/geofences)