Skip to content

Create a geofence and activate it

POST
/integration/v1/organizations/{organization}/geofences
curl --request POST \
--url https://api.elwids.xyz/api/integration/v1/organizations/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/geofences \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "operation_uuid": "9f8e7d6c-5b4a-4392-8170-6f5e4d3c2b1a", "expected_revision": 0, "name": "North paddock", "geometry": { "type": "Polygon", "coordinates": [ [ [ -114.01, 50.99 ], [ -113.99, 50.99 ], [ -113.99, 51.01 ], [ -114.01, 51.01 ], [ -114.01, 50.99 ] ] ] }, "assignments": [ { "device_uuid": "3f8a1c2e-5b6d-4e7f-8a9b-0c1d2e3f4a5b", "policy": { "outside_for_seconds": 60, "max_gap_seconds": 45, "minimum_samples": 2, "uncertainty_metres": 2 } } ] }'

Requires: geofences:activate and geofences:manage

Rate limits: 240 a minute per address, 60 a minute per application

Saves a new geofence (revision 1) with one workflow per assigned device, then starts their activation and returns 202 with the activation to poll. Needs geofences:activate and geofences:manage. Idempotent on operation_uuid. 403 when an assigned device is not granted; 404 when an assigned device has no location binding; 409 when operation_uuid was used for a different request or expected_revision is not 0; 422 for invalid input, or when the runtime rejects the geofence (a message, or errors.runtime); 503 when the runtime is unavailable.

organization
required
string format: uuid

The organization UUID. A value that does not match returns 404.

Media typeapplication/json

A geofence to save and activate. Every assigned device must be granted to the application and have a location binding.

object
operation_uuid
required

Idempotency key and the activation’s UUID. Repeating the same request returns the same result; reusing it for a different request returns 409.

string format: uuid
expected_revision

The revision the client last read; a stale value returns 409. Defaults to 0 when creating (which must stay 0) and to the current revision when updating.

integer
name
required
string
<= 255 characters
geometry
required

Only type and coordinates; any other member is rejected.

object
type
required
Allowed value: Polygon
coordinates
required
Array<Array<array>>
>= 1 items <= 1 items
assignments
required

Devices to assign; each device_uuid at most once. Devices left out are removed.

Array<object>
>= 1 items <= 100 items
object
device_uuid
required
string format: uuid
policy
required

When a device counts as wandering outside the geofence.

object
outside_for_seconds
required
integer
<= 86400
max_gap_seconds
required
integer
>= 1 <= 86400
minimum_samples
required
integer
>= 1 <= 1000
uncertainty_metres
required
number
<= 100000

Example

{
"operation_uuid": "9f8e7d6c-5b4a-4392-8170-6f5e4d3c2b1a",
"expected_revision": 0,
"name": "North paddock",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-114.01,
50.99
],
[
-113.99,
50.99
],
[
-113.99,
51.01
],
[
-114.01,
51.01
],
[
-114.01,
50.99
]
]
]
},
"assignments": [
{
"device_uuid": "3f8a1c2e-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"policy": {
"outside_for_seconds": 60,
"max_gap_seconds": 45,
"minimum_samples": 2,
"uncertainty_metres": 2
}
}
]
}

Saved; the activation is under way. Poll activation.

Media typeapplication/json

The saved geofence and the activation to poll.

object
data
required

A geofence, with only the assignments of devices granted to the application.

object
uuid
required
string format: uuid
name
required
string
geometry
required

A GeoJSON Polygon with one ring of 4 to 257 positions.

object
type
required
Allowed value: Polygon
coordinates
required
Array<Array<array>>
>= 1 items <= 1 items
revision
required
integer
>= 1
created_at
required
string format: date-time
updated_at
required
string format: date-time
assignments
required
Array<object>

One device assigned to the geofence, with its own workflow.

object
uuid
required
string format: uuid
policy
required

When a device counts as wandering outside the geofence.

object
outside_for_seconds
required
integer
<= 86400
max_gap_seconds
required
integer
>= 1 <= 86400
minimum_samples
required
integer
>= 1 <= 1000
uncertainty_metres
required
number
<= 100000
desired_geofence_revision
required
integer
>= 1
applied_geofence_revision
required
integer | null
>= 1
status
required

pending, active, failed or removing.

string
diagnostic
required
string | null
device
required
object
uuid
required
string format: uuid
name
required
string
code
required
string
workflow_uuid
required
string format: uuid
deployment_status
required

The assignment workflow’s deployment status, for example pending, active or inactive.

string
activation
required

The activation of one geofence revision: one item per assignment to activate or remove. Poll it until status is no longer pending.

object
uuid
required

The operation_uuid the client sent.

string format: uuid
geofence_revision
required
integer
>= 1
status
required
string
Allowed values: pending partial_failure succeeded
created_at
required
string format: date-time
updated_at
required
string format: date-time
items
required
Array<object>
object
id
required

Pass as item to retry a failed item.

integer
>= 1
assignment_uuid
required
string format: uuid
device_uuid
required
string format: uuid
operation_uuid
required

The workflow deployment that applies this item.

string format: uuid
target
required
string
Allowed values: active inactive
status
required

pending, succeeded or failed, following the workflow deployment.

string
diagnostic
required
string | null

Example

{
"data": {
"uuid": "1e2d3c4b-5a69-4788-9a6b-5c4d3e2f1a0b",
"name": "North paddock",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-114.01,
50.99
],
[
-113.99,
50.99
],
[
-113.99,
51.01
],
[
-114.01,
51.01
],
[
-114.01,
50.99
]
]
]
},
"revision": 1,
"created_at": "2026-10-12T08:00:00.000000Z",
"updated_at": "2026-10-12T08:00:00.000000Z",
"assignments": [
{
"uuid": "4c5d6e7f-8a9b-4c0d-9e1f-2a3b4c5d6e7f",
"policy": {
"outside_for_seconds": 60,
"max_gap_seconds": 45,
"minimum_samples": 2,
"uncertainty_metres": 2
},
"desired_geofence_revision": 1,
"applied_geofence_revision": null,
"status": "pending",
"diagnostic": null,
"device": {
"uuid": "3f8a1c2e-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"name": "Herd tracker 17",
"code": "tracker-017"
},
"workflow_uuid": "5a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"deployment_status": "pending"
}
]
},
"activation": {
"uuid": "9f8e7d6c-5b4a-4392-8170-6f5e4d3c2b1a",
"geofence_revision": 1,
"status": "pending",
"created_at": "2026-10-12T08:00:00.000000Z",
"updated_at": "2026-10-12T08:00:00.000000Z",
"items": [
{
"id": 41,
"assignment_uuid": "4c5d6e7f-8a9b-4c0d-9e1f-2a3b4c5d6e7f",
"device_uuid": "3f8a1c2e-5b6d-4e7f-8a9b-0c1d2e3f4a5b",
"operation_uuid": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"target": "active",
"status": "pending",
"diagnostic": null
}
]
}
}
Cache-Control
required
string
/(^|[ ,])no-store([ ,]|$)/

Responses to authenticated integration requests are never cached. The header also carries private.

Example
no-store, private

No valid credentials: no session (first-party API), or a missing, invalid, expired or revoked application token (integration API).

Media typeapplication/json

The body of most error responses.

object
message
required
string

Example generated

{
"message": "example"
}

The caller is not allowed: not a member of the organization, missing a tenant or platform permission, or (integration API) an ability not granted on both the application and the token.

Media typeapplication/json

The body of most error responses.

object
message
required
string

Example generated

{
"message": "example"
}

Not found: an unknown organization or resource, a resource in another organization or not granted to the application, or a malformed identifier (the route does not match).

Media typeapplication/json

The body of most error responses.

object
message
required
string

Example generated

{
"message": "example"
}

The request conflicts with the current state, for example a stale revision.

Media typeapplication/json

The body of most error responses.

object
message
required
string

Example generated

{
"message": "example"
}

The input failed validation (errors names the fields), or the request cannot be applied in the resource’s current state (a message only, for example an archived device or a limit reached).

Media typeapplication/json
Any of:

422 for input that failed validation.

object
message
required

The first error, followed by a count of the others.

string
errors
required

Messages per field, keyed by the field’s dotted path. A rejection by the device runtime appears under runtime.

object
runtime
Array<string>
key
additional properties
Array<string>

Example generated

{
"message": "example",
"errors": {
"runtime": [
"example"
]
}
}

A rate limit was reached; see x-rate-limits on the operation.

Media typeapplication/json

The body of most error responses.

object
message
required
string

Example generated

{
"message": "example"
}
Retry-After
required
integer

Seconds to wait before retrying.

The device runtime is not configured, unavailable, or could not complete the request.

Media typeapplication/json

The body of most error responses.

object
message
required
string

Example generated

{
"message": "example"
}

Report a problem with this page