> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mile.app/llms.txt
> Use this file to discover all available pages before exploring further.

# On Geofence Leave

## Overview

The **On Geofence Leave** automation event triggers when a field worker's GPS position leaves a geofence they had previously entered. The automation sends the crossing to an external HTTP endpoint, so an operations dashboard, WMS, or ERP can react the moment a worker departs a store, warehouse, customer site, or restricted area.

It is the counterpart to [On Geofence Entry](/pages/automation/automation-event/on-geofence-entry) and is configured the same way, on the same geofence group.

<Note>
  Required permission:

  * View Automation
  * Create Automation
  * View Geofence
</Note>

## Availability

Geofence is not generally available yet. It is enabled for MileApp internal staff and for pilot organizations that have been explicitly allowlisted. If your organization is not in the rollout, the geofence menus and the geofence API return **404 Not Found**, and the On Geofence Leave option does not appear in the event dropdown. Contact MileApp support if you would like your organization included.

## Constraints

Two constraints apply to this event and are enforced by the API:

1. **Webhook only.** `Webhook` is the only automation type accepted. Create Task, Create and Assign Task, Move Task, Assign Task, Update Task, Create or Update Data Source, and Notification are all rejected with `400 Bad Request`.
2. **A geofence group is required.** The automation is scoped to exactly one geofence group, chosen in the **Geofence Group** picker. Saving without one fails validation.

## When Does This Event Trigger?

1. The field worker's mobile app reports a GPS position outside a geofence they were recorded as inside.
2. MileApp checks whether the matching **entry** for that geofence was announced.
3. If it was, the leave event fires and the webhook is sent. If it was not, nothing is sent.

**A leave never fires without its entry.** If the worker only clipped the corner of a geofence and left before the dwell time elapsed, no entry event was sent, so no leave event is sent either. This avoids a "left" arriving at your endpoint with no matching "entered", which would look like a bug on your side.

Because the entry has to have fired first, the pairing is reliable: every On Geofence Leave you receive corresponds to an On Geofence Entry you already received for the same worker and the same geofence.

## Setting Up On Geofence Leave Automation

### Step 1: Create the Geofence and Group

1. Draw the geofences you want to watch and place them in a geofence group
2. Set each geofence's dwell time, this still governs whether the paired entry fires
3. Make sure each geofence is **active**, inactive geofences are ignored

### Step 2: Create the Automation

1. Log in to the MileApp web portal
2. Click **Flow** in the main navigation, then open the **Automation** tab
3. Click **New**
4. **Automation Name:** a descriptive name, for example "Notify WMS on store departure"
5. **Event:** select **On Geofence Leave**
6. **Geofence Group:** select the group to watch (required)
7. **Automation Type:** **Webhook** (the only option for this event)

### Step 3: Configure the Webhook

1. **URL:** the endpoint that should receive the crossing. Required, and must be a valid URL
2. **Header (Optional):** custom HTTP headers, for example `Authorization`
3. **Value (Optional):** the matching header value

```
URL: https://api.yourcompany.com/webhook/geofence-leave
Header: Authorization
Value: Bearer your_api_token_here
```

### Step 4: Save and Activate

1. Click **Submit**
2. Confirm the automation toggle is **Active**
3. Test by having a field worker enter one of the group's geofences, stay past the dwell time, then leave

## Webhook Payload

MileApp sends a POST request whose body is the location history record with the geofence details merged onto it. The shape is identical to On Geofence Entry apart from `eventName`.

```json theme={null}
{
  "_id": "663b2c3d4f1a2b3c4d5e6f80",
  "eventName": "leave_geofence",
  "email": "driver@example.com",
  "organizationId": "660a1b2c4f1a2b3c4d5e6f03",
  "taskId": null,
  "lat": -6.2093,
  "lon": 106.8461,
  "speed": 18,
  "createdFrom": "app",
  "isLatest": true,
  "createdTime": "2026-07-20T08:47:00.000Z",
  "geofenceId": "gf_123",
  "geofenceName": "Store A Sudirman",
  "geofenceGroupId": "66c1a4f2d3b19f0012ab77e4",
  "geofenceGroup": "Visit Store",
  "dwellMinutes": 5
}
```

### Geofence Fields

| Field             | Type    | Description                                                              |
| ----------------- | ------- | ------------------------------------------------------------------------ |
| `eventName`       | string  | Always `leave_geofence` for this event                                   |
| `geofenceId`      | string  | The specific geofence that was left                                      |
| `geofenceName`    | string  | Display name of that geofence                                            |
| `geofenceGroupId` | string  | Id of the group, the value the automation is scoped to                   |
| `geofenceGroup`   | string  | **Name** of that group                                                   |
| `dwellMinutes`    | integer | The geofence's configured dwell time, not the time actually spent inside |

`geofenceGroup` is the group name meant for display; `geofenceGroupId` is the id used for matching. They are different fields, do not treat them as interchangeable.

### Location Fields

| Field            | Type    | Description                                                  |
| ---------------- | ------- | ------------------------------------------------------------ |
| `_id`            | string  | Id of the location history record that produced the crossing |
| `email`          | string  | Email address of the field worker                            |
| `organizationId` | string  | Your organization id                                         |
| `taskId`         | string  | Associated task id, `null` when the worker was not on a task |
| `lat`            | float   | Latitude at the moment of the crossing                       |
| `lon`            | float   | Longitude at the moment of the crossing                      |
| `speed`          | float   | Reported speed                                               |
| `createdFrom`    | string  | Source of the position: `app` or `api`                       |
| `isLatest`       | boolean | Whether this was the worker's newest reported position       |
| `createdTime`    | string  | Timestamp of the position report                             |

## Response

Your endpoint must return an HTTP 200 status code to acknowledge receipt:

```json theme={null}
{
  "status": "received"
}
```

## Tracking List Markers

When a geofence leave matches one of your automations, MileApp also writes a marker into the worker's Tracking List slider so the crossing is visible in the web portal.

The marker is written **only when an automation matched**. An organization with geofences drawn but no On Geofence Leave automation on that group sees no markers. A worker with no task on the selected day shows nothing in the slider at all, which is normal slider behaviour and not related to geofence.

## Monitoring and Troubleshooting

### Viewing Automation Logs

1. Go to **Flow > Automation**
2. Find your automation in the list
3. Click the **clock history** icon to view execution logs
4. Review successful executions and errors

### Common Issues

**Issue:** The leave event never fires

**Possible Causes:**

* The paired entry never fired, because the worker did not stay past the dwell time
* The automation is not Active
* The geofence belongs to a different group than the one selected on the automation
* The mobile app stopped reporting positions before the worker left the geofence
* Your organization is not in the geofence rollout

**Solution:**

* Confirm you received the matching On Geofence Entry first, no entry means no leave
* Confirm the automation toggle is ON and the geofence is active
* Check that the geofence sits in the selected group
* Check that the app was reporting positions for the whole visit

**Issue:** Entry fired but the leave arrived much later than expected

**Explanation:** The leave is decided from the first reported position outside the geofence. If the app stopped reporting inside the zone, for example the device lost signal, the crossing is only detected once positions resume.

**Issue:** Webhook not receiving data

**Possible Causes:**

* Incorrect webhook URL
* Authentication headers missing or incorrect
* The external endpoint is down or unreachable

**Solution:**

* Verify the URL is reachable from the public internet
* Check the authentication credentials
* Review the automation logs for the response status and body

## Related Documentation

* [On Geofence Entry](/pages/automation/automation-event/on-geofence-entry)
* [Webhook Automation](/pages/automation/automation-type/webhook)
* [Automation Event Introduction](/pages/automation/automation-event/introduction)

## Frequently Asked Questions

**Q: Do I need a separate automation for entry and leave?**

A: Yes. Entry and leave are two events, so each needs its own automation. Both can point at the same geofence group and the same webhook URL, and you can tell them apart by `eventName`.

**Q: Can one automation watch several geofence groups?**

A: No. Each automation is scoped to exactly one group. Create one automation per group.

**Q: Does the payload tell me how long the worker stayed inside?**

A: No. `dwellMinutes` is the geofence's configured threshold. To measure the visit, compare `createdTime` on the leave payload against `createdTime` on the matching entry payload.

**Q: Can I use Create Task or Notification with this event?**

A: No. Webhook is the only automation type accepted, and any other type is rejected with a 400 error.
