> This page is part of the [Customer.io documentation](https://docs.customer.io). For the complete index, see [llms.txt](https://docs.customer.io/llms.txt).
> Last updated: October 26, 2026
> To take actions in Customer.io from an agent, use the [Customer.io CLI](https://docs.customer.io/ai/cli/get-started.md) or the [MCP server](https://docs.customer.io/ai/mcp/get-started.md).

# Import geofences

Import circles and polygons into a geofence set from a GeoJSON, GeoJSONL, or CSV file.

To import multiple geofences, first [create a geofence set](https://docs.customer.io/messaging/people/location/manage-geofences/#create-a-geofence-set). Then create either a [GeoJSON file](#geojson) or [CSV file](#csv) with the required fields. You can import up to 10,000 geofences per geofence set, and the file must be less than 32 MB. GeoJSON files, including GeoJSONL files, can contain circles, polygons, or both. CSV files only support circles.

You can also import a file with the [import endpoint in the App API](https://docs.customer.io/integrations/api/app/tag/imports/import/) by setting `type` to `geoset`. The file uses the same formats and fields as an import in the UI, and your set’s `geoset_id` is the number after `geosets/` in the set’s URL.

1.  Select a geofence set.
2.  Click **Import**.
3.  Upload a [GeoJSON](#geojson) or [CSV](#csv) file.
4.  Decide how to run the import:
    *   Choose **Add and update** if you want to add new geofences and update existing geofences. [If the geofence shares an ID with other geofences, every geofence with that ID updates to match the new settings, even if the geofence is in a different geofence set.](https://docs.customer.io/messaging/people/location/manage-geofences/#sync-shared-geofences-across-geofence-sets)
    *   Choose **Replace all** if you want to replace all geofences in the set with only what’s in the import file. This only removes geofences from this set; if a deleted geofence shares an ID with a geofence in another set, the other geofence set keeps the geofence.
5.  Click **Import files**.

You can preview the geofences after importing.

## GeoJSON

**GeoJSON** is a geospatial data interchange format based on JavaScript Object Notation (JSON). You can learn about the spec through the [IETF ↗](https://datatracker.ietf.org/doc/html/rfc7946) and validate your spec before import at [geojson.io ↗](https://geojson.io/).

This example contains a circular geofence and a polygon geofence:

```
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": "hq-sf",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -122.4194,
          37.7749
        ]
      },
      "properties": {
        "name": "HQ",
        "radius": 250,
        "promo_code": "HQ10"
      }
    },
    {
      "type": "Feature",
      "id": "campus-sf",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [-122.394, 37.794],
            [-122.39, 37.794],
            [-122.39, 37.798],
            [-122.394, 37.798],
            [-122.394, 37.794]
          ]
        ]
      },
      "properties": {
        "name": "Campus",
        "promo_code": "CAMPUS10"
      }
    }
  ]
}
```

The following fields are required unless noted otherwise:

Field

Description

`type`

Must be “FeatureCollection”

`features`

An array of objects, where each object is a geofence

`features.type`

Must be “Feature”

`features.id`

A unique identifier for the feature; if you leave this blank, Customer.io generates a UUID

`features.geometry`

An object with a `type` and `coordinates`

`features.geometry.type`

Use `Point` for a circle or `Polygon` for a polygon. You can’t use other geometry types, including `MultiPolygon`.

`features.geometry.coordinates`

For a circle, use `[<longitude>, <latitude>]`. For a polygon, use one array of coordinate pairs that meets the [polygon requirements](#polygon-requirements).

`features.properties`

An object with a `name` and any additional custom properties you want to store with the geofence. Circles also require a `radius`.

`features.properties.name`

The name of your geofence

`features.properties.radius`

Required for circles. Integer representing the radius in meters, from 100–10,000. Remove this property from polygons; otherwise, validation rejects the feature. Customer.io calculates the enclosing circle from the polygon boundary.

`features.properties.dwell_threshold_seconds`

(Optional) The time, in seconds, that a person needs to stay inside the geofence before the SDK sends a dwell event. Use `0` or `null` to turn dwell events off. Omit this property to keep the current dwell time.

`features.properties.<custom>`

(Optional) Any additional properties—like a location ID, category, or deeplink slug—are stored as the geofence’s attributes. Values keep their JSON types, so numbers and `true`/`false` stay numbers and booleans.

Importing metadata

To import metadata with your geofences, add your own keys to each feature’s `properties` object. Customer.io stores those custom properties as geofence attributes. For polygons, don’t add `latitude`, `longitude`, or `radius` to `properties`; validation rejects a polygon that contains any of those reserved properties. CSV files can carry custom attributes too, but Customer.io stores every CSV value as text.

You can also upload a GeoJSONL file (`.geojsonl`), which puts one `Feature` object on each line instead of wrapping features in a `FeatureCollection`. Each line uses the same `features.*` fields as the preceding table. When you [export a geofence set](https://docs.customer.io/messaging/people/location/manage-geofences/#export-a-list-of-geofences), Customer.io writes the export in this format, so you can edit an export and import it again without converting it.

## CSV

To import multiple geofences from a CSV file, create a CSV file with these fields. All fields are required except where noted:

Field

Description

`name`

The name of your geofence

`radius`

Integer. Represents radius in meters. Must be within 100–10,000.

`longitude`

The longitude of your geofence

`latitude`

The latitude of your geofence

`external_id`

(Optional) A unique identifier for the feature; if you leave this blank, Customer.io generates a UUID

`dwell_threshold_seconds`

(Optional) The time, in seconds, that a person needs to stay inside the geofence before the SDK sends a dwell event. Use `0` to turn dwell events off. Leave empty to keep the current dwell time.

Any other column becomes a custom attribute on each geofence, named after the column header. Customer.io stores these values as text, so use GeoJSON if you need an attribute to be a number or `true`/`false`. Use the column names in the table exactly as written, in lowercase. A column that only differs from one of them by capitalization, like `Name`, makes the import fail.

From the import UI, you can download a CSV template to help you create your file.

## Polygon requirements

Whether you draw a polygon in Customer.io or import it with GeoJSON, it must meet these requirements:

*   Use one boundary with 3–500 points.
*   Use a convex shape. The boundary can’t turn inward or include a cut-out, such as an L or T shape. To exclude a building at the corner of a larger area, use two rectangular geofences to cover the remaining space. Customer.io tracks each rectangle as a separate geofence.
*   Don’t use holes, crossing edges, or duplicate adjacent points.
*   The enclosing radius of the polygon must be no smaller than 100 meters and no larger than 10 kilometers.
*   Keep every point between -85° and 85° latitude, and don’t draw a polygon across the 180° longitude line.

For GeoJSON imports, you must also:

*   Close the boundary by repeating its first point at the end. The repeated closing point does not count toward the 500-point limit.
*   Start each coordinate with longitude followed by latitude. Customer.io ignores additional numeric values such as altitude, but rejects non-numeric values.
*   Remove `latitude`, `longitude`, and `radius` from the feature’s `properties`. Customer.io calculates the center and enclosing circle from the polygon boundary.

If a GeoJSON file contains at least one polygon, every feature in the file must be valid before you can import it.

### Polygons must be convex

Mobile operating systems don’t report polygon crossings, so the SDK works out for itself which side of the boundary a person is on. Each location reading comes with an accuracy radius: how far off the real position might be. A reading that lands within that distance of the boundary could belong on either side, so it’s less reliable than one that lands well inside or well outside.

Concave shapes have pockets of outside space that reach into the boundary. The U below is an extreme example, but any inward turn creates a smaller pocket. A reading in a narrow pocket can land near both walls, and it can be tough to determine whether someone is in or out of the boundary. Because these pockets make detection less reliable, Customer.io only supports convex polygons for now.

Convex boundary

Uncertainty stays in a thin strip along the edge, and a straight walk across the inside never crosses the boundary.

Concave boundary

A gap that reaches into the shape puts a reading near two walls at once, and the same walk leaves the boundary and comes back.

location reading accuracy radius someone walking past too close to the edge to be sure
