Skip to content
getgeolens.com

Create Feature

POST
/datasets/{dataset_id}/features/
curl --request POST \
--url https://example.com/datasets/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/features/ \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "geometry": { "type": "GeometryCollection", "geometries": [ { "type": "Point", "coordinates": [ "example" ] } ] }, "properties": {} }'

Insert a new GeoJSON feature into a dataset.

Send the same Idempotency-Key on every attempt to create one feature, and Idempotency-Attempt numbering the attempts 1, 2, 3 and so on. A repeat from the same user on the same dataset never inserts a second feature. It answers with the feature as stored, with the same 201 status and body shape. If its attempt number is higher than any applied so far, it first applies its geometry and the properties it names to that feature, with the validation a create gets, unless anyone else has written the feature since the last attempt was applied: then it is refused with 409, the stored feature in detail.feature, and nothing is overwritten. If it is equal or lower, the stored feature comes back unchanged, so a request that arrives late cannot undo a later one. Two requests with one key never both insert. A key is honored for 24 hours. If the feature it created has been deleted since, or the dataset’s data has been replaced by a reupload or an overwrite, the repeat is refused with 409 rather than creating another. Without the key every request inserts, and an attempt number sent without one is ignored.

Through an append-only dataset key, every created feature, single or in a FeatureCollection, is answered with its id, a null geometry, empty properties, and null table_id and tile_cache_version, since the stored row can hold values the key didn’t send and the others move with other writers. A repeat through one matches only that key’s own creates, applies nothing and answers the same way. If the feature was deleted or the dataset’s data replaced, the repeat gets 409 feature_gone with no tile_cache_version.

A GeoJSON FeatureCollection body inserts up to 1,000 features in one transaction: all of them or none. A feature the schema refuses is named by its position under features in the 422. One refused while writing gets the status a single create would, with detail.code feature_refused, detail.index (counting from 0) and detail.message. The 201 answer is a FeatureCollection of the stored features in request order, each as a single create returns it, with table_id and tile_cache_version also on the collection. It has no Location header since there is no single new resource. Idempotency-Key is refused with 422 for a FeatureCollection.

dataset_id
required
Dataset Id
string format: uuid
Idempotency-Key
Idempotency-Key

Optional key that makes a retried create safe. Any visible ASCII character (! to ~, no spaces), 1 to 128 characters. The key is compared exactly as sent, so a quoted key and the same key unquoted are different keys. For example device-42:2026-10-17T16:09:33.123000+00:00.

string
>= 1 characters <= 128 characters /^[!-~]+$/

Optional key that makes a retried create safe. Any visible ASCII character (! to ~, no spaces), 1 to 128 characters. The key is compared exactly as sent, so a quoted key and the same key unquoted are different keys. For example device-42:2026-10-17T16:09:33.123000+00:00.

Idempotency-Attempt
Idempotency-Attempt

Attempt number sent with Idempotency-Key, counting up by one each time the body is sent again. Counts as 1 when omitted.

integer
>= 1 <= 2147483647

Attempt number sent with Idempotency-Key, counting up by one each time the body is sent again. Counts as 1 when omitted.

Media type application/json
Any of:
FeatureCreate

GeoJSON-style feature for insertion.

object
geometry
required
Any of:
GeoJSONGeometryCollection

A GeoJSON GeometryCollection (RFC 7946 §3.1.8).

Geometry collections carry geometries instead of coordinates. Only generic-geometry datasets accept them on write.

Nested collections are rejected because PostGIS cannot round-trip them through the GeoJSON boundary.

object
type
required
Type
string
Allowed value: GeometryCollection
geometries
required
Geometries
Array<object>
GeoJSONGeometry

A GeoJSON geometry object (RFC 7946).

object
type
required
Type
string
Allowed values: Point MultiPoint LineString MultiLineString Polygon MultiPolygon
coordinates
required
Coordinates
Array
properties
Any of:
object
key
additional properties
any

Successful Response

One of:
GeoJSONFeature

A written GeoJSON Feature, plus the dataset’s committed tile version.

object
type
Type
string
default: Feature
Allowed value: Feature
id
required
Id
integer
geometry
Any of:
GeoJSONGeometryCollection

A GeoJSON GeometryCollection (RFC 7946 §3.1.8).

Geometry collections carry geometries instead of coordinates. Only generic-geometry datasets accept them on write.

Nested collections are rejected because PostGIS cannot round-trip them through the GeoJSON boundary.

object
type
required
Type
string
Allowed value: GeometryCollection
geometries
required
Geometries
Array<object>
GeoJSONGeometry

A GeoJSON geometry object (RFC 7946).

object
type
required
Type
string
Allowed values: Point MultiPoint LineString MultiLineString Polygon MultiPolygon
coordinates
required
Coordinates
Array
properties
required
Properties
object
key
additional properties
any
table_id
Any of:
string
tile_cache_version
Any of:
integer

Example

{
"type": "Feature",
"geometry": {
"type": "GeometryCollection",
"geometries": [
{
"type": "Point"
}
]
}
}

Bad request — invalid payload

Media type application/problem+json
ProblemDetail
object
type
Type
string
default: about:blank
title
required
Title
string
status
required
Status
integer
detail
required
Any of:
string

Example

{
"detail": "Dataset not found",
"status": 404,
"title": "Not Found",
"type": "about:blank"
}

Unauthorized — missing or invalid credentials

Media type application/problem+json
ProblemDetail
object
type
Type
string
default: about:blank
title
required
Title
string
status
required
Status
integer
detail
required
Any of:
string

Example

{
"detail": "Dataset not found",
"status": 404,
"title": "Not Found",
"type": "about:blank"
}

Forbidden — caller lacks write access

Media type application/problem+json
ProblemDetail
object
type
Type
string
default: about:blank
title
required
Title
string
status
required
Status
integer
detail
required
Any of:
string

Example

{
"detail": "Dataset not found",
"status": 404,
"title": "Not Found",
"type": "about:blank"
}

Not found

Media type application/problem+json
ProblemDetail
object
type
Type
string
default: about:blank
title
required
Title
string
status
required
Status
integer
detail
required
Any of:
string

Example

{
"detail": "Dataset not found",
"status": 404,
"title": "Not Found",
"type": "about:blank"
}

Conflict — resource state prevents the operation

Media type application/problem+json
ProblemDetail
object
type
Type
string
default: about:blank
title
required
Title
string
status
required
Status
integer
detail
required
Any of:
string

Example

{
"detail": "Dataset not found",
"status": 404,
"title": "Not Found",
"type": "about:blank"
}

Validation error

Media type application/problem+json
ProblemDetail
object
type
Type
string
default: about:blank
title
required
Title
string
status
required
Status
integer
detail
required
Any of:
string

Example

{
"detail": "Dataset not found",
"status": 404,
"title": "Not Found",
"type": "about:blank"
}

Too many requests — retry after the advertised interval

Media type application/problem+json
ProblemDetail
object
type
Type
string
default: about:blank
title
required
Title
string
status
required
Status
integer
detail
required
Any of:
string

Example

{
"detail": "Dataset not found",
"status": 404,
"title": "Not Found",
"type": "about:blank"
}
Retry-After
integer

Seconds until the request may be retried

Internal server error

Media type application/problem+json
ProblemDetail
object
type
Type
string
default: about:blank
title
required
Title
string
status
required
Status
integer
detail
required
Any of:
string

Example

{
"detail": "Dataset not found",
"status": 404,
"title": "Not Found",
"type": "about:blank"
}

Service unavailable — the database could not serve the request

Media type application/problem+json
ProblemDetail
object
type
Type
string
default: about:blank
title
required
Title
string
status
required
Status
integer
detail
required
Any of:
string

Example

{
"detail": "Dataset not found",
"status": 404,
"title": "Not Found",
"type": "about:blank"
}