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

# OGC WFS 2.0

> Resources, examples, configuration and evidence for OGC WFS 2.0.

Use the `@bijection/connectors/wfs` entrypoint to declare OGC WFS 2.0 resources.

## Availability

This page describes the pinned source package. Published availability is unestablished for this artifact. [Source build and package availability](https://docs.bijection.com/client/sdk-distribution.md).

## Resources and modes

| Resource | Mode | Description |
| - | - | - |
| Feature type | `keyset` | GeoJSON keyset walk |

Declare a resource in application code, then bind deployment-specific settings and credentials. See [typed resources](https://docs.bijection.com/integrations/resources.md), [connections](https://docs.bijection.com/integrations/connections.md) and [source inspection](https://docs.bijection.com/integrations/cli.md).

## Feature type

### keyset: GeoJSON keyset walk

The following example matches configuration `roads`.

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { wfs } from "@bijection/connectors/wfs";
import { v } from "bijection/values";

export const roads = wfs.featureType.keyset({
  idProperty: "gid",
  properties: {
    name: v.union(v.string(), v.null()),
    lanes: v.union(v.int64(), v.null()),
  },
  geometry: { types: ["LineString", "MultiLineString"] },
  pageSize: 2,
});
```

> **Inferred record types**
>
> ```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
> {
>   "featureId": bigint;
>   "geometry": any;
>   "name": string | null;
>   "lanes": bigint | null;
> }
> ```

#### Configuration: roads

Case: `wfs/featureType/keyset/roads`.

Connection and resource configuration are declared by this exact case.

Credential kind: `wfs`. Keep credential material in the private credential inventory.

| Setting | Type | Required | Owner |
| - | - | - | - |
| `endpoint` | string | Yes | Shared connection |
| `typeName` | string | Yes | Resource binding |

> **Complete configuration contract**
>
> ```json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
> {
>   "setup": [],
>   "resource": {
>     "access": {},
>     "defaults": {},
>     "connector": "wfs",
>     "output": {
>       "kind": "single",
>       "collection": "records"
>     },
>     "credential_kind": "wfs",
>     "connection_fields": [
>       "endpoint"
>     ],
>     "address": {
>       "kind": "setup",
>       "field": "endpoint"
>     }
>   },
>   "connection_setup": {
>     "type": "object",
>     "value": {
>       "endpoint": {
>         "fieldType": {
>           "type": "string"
>         },
>         "optional": false
>       },
>       "typeName": {
>         "fieldType": {
>           "type": "string"
>         },
>         "optional": false
>       }
>     }
>   },
>   "execution": null
> }
> ```

Native admission analysis is available for this exact declaration.

**Collection: records**

| Contract | Meaning |
| - | - |
| Initial | Enumeration of observed records |
| Changes | Repeated observations of current records |
| Deletions | Deletion detection unsupported |
| Resume | Opaque cursor |
| Gap | Explicit repair required after a gap |
| Retention | Unspecified |

> **Complete native profile**
>
> ```json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
> {
>   "movement": {
>     "exchanges": {
>       "records": {
>         "200": {
>           "placement": "retained_bytes",
>           "interpretation": "json",
>           "projectsBeforeRetention": false,
>           "retainedBodyLimitBytes": "524288",
>           "fileLimitBytes": null
>         }
>       },
>       "records_after": {
>         "200": {
>           "placement": "retained_bytes",
>           "interpretation": "json",
>           "projectsBeforeRetention": false,
>           "retainedBodyLimitBytes": "524288",
>           "fileLimitBytes": null
>         }
>       }
>     },
>     "nativeInputLimitBytes": null,
>     "steps": [
>       {
>         "id": "acquire.1",
>         "inputs": [],
>         "action": {
>           "operation": "acquire",
>           "subject": "exchange records",
>           "limitBytes": null
>         }
>       },
>       {
>         "id": "acquire.2",
>         "inputs": [],
>         "action": {
>           "operation": "acquire",
>           "subject": "exchange records_after",
>           "limitBytes": null
>         }
>       },
>       {
>         "id": "retain.1",
>         "inputs": [
>           "acquire.1",
>           "acquire.2"
>         ],
>         "action": {
>           "operation": "retain",
>           "subject": "acquisition evidence",
>           "reason": "recovery",
>           "release": "acquisition_custody"
>         }
>       },
>       {
>         "id": "interpret.1",
>         "inputs": [
>           "retain.1"
>         ],
>         "action": {
>           "operation": "interpret",
>           "subject": "acquired input",
>           "produces": "records"
>         }
>       },
>       {
>         "id": "materialize.1",
>         "inputs": [
>           "interpret.1"
>         ],
>         "action": {
>           "operation": "materialize",
>           "subject": "source rows",
>           "reason": "serving",
>           "release": "replacement"
>         }
>       },
>       {
>         "id": "publish.1",
>         "inputs": [
>           "materialize.1"
>         ],
>         "action": {
>           "operation": "publish",
>           "subject": "source rows",
>           "visibility": "with_acquisition"
>         }
>       }
>     ]
>   },
>   "initial": "enumeration",
>   "changes": "observations",
>   "deletions": "unsupported",
>   "resume": "opaque_cursor",
>   "retentionMs": null,
>   "gap": "explicit_repair",
>   "limits": {
>     "http_response_bytes": "524288"
>   },
>   "restrictions": [],
>   "commands": {}
> }
> ```

> **Commands, occurrences and artifacts**
>
> ```json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
> {
>   "records": {
>     "records": {
>       "protocol": "record_observation",
>       "coverage": "records",
>       "consistency": "observations",
>       "atomicity": "record",
>       "history": "observations",
>       "recordRefresh": false,
>       "reconciliation": false,
>       "notifications": false,
>       "snapshotMaxRows": null,
>       "profile": {
>         "movement": {
>           "exchanges": {
>             "records": {
>               "200": {
>                 "placement": "retained_bytes",
>                 "interpretation": "json",
>                 "projectsBeforeRetention": false,
>                 "retainedBodyLimitBytes": "524288",
>                 "fileLimitBytes": null
>               }
>             },
>             "records_after": {
>               "200": {
>                 "placement": "retained_bytes",
>                 "interpretation": "json",
>                 "projectsBeforeRetention": false,
>                 "retainedBodyLimitBytes": "524288",
>                 "fileLimitBytes": null
>               }
>             }
>           },
>           "nativeInputLimitBytes": null,
>           "steps": [
>             {
>               "id": "acquire.1",
>               "inputs": [],
>               "action": {
>                 "operation": "acquire",
>                 "subject": "exchange records",
>                 "limitBytes": null
>               }
>             },
>             {
>               "id": "acquire.2",
>               "inputs": [],
>               "action": {
>                 "operation": "acquire",
>                 "subject": "exchange records_after",
>                 "limitBytes": null
>               }
>             },
>             {
>               "id": "retain.1",
>               "inputs": [
>                 "acquire.1",
>                 "acquire.2"
>               ],
>               "action": {
>                 "operation": "retain",
>                 "subject": "acquisition evidence",
>                 "reason": "recovery",
>                 "release": "acquisition_custody"
>               }
>             },
>             {
>               "id": "interpret.1",
>               "inputs": [
>                 "retain.1"
>               ],
>               "action": {
>                 "operation": "interpret",
>                 "subject": "acquired input",
>                 "produces": "records"
>               }
>             },
>             {
>               "id": "materialize.1",
>               "inputs": [
>                 "interpret.1"
>               ],
>               "action": {
>                 "operation": "materialize",
>                 "subject": "source rows",
>                 "reason": "serving",
>                 "release": "replacement"
>               }
>             },
>             {
>               "id": "publish.1",
>               "inputs": [
>                 "materialize.1"
>               ],
>               "action": {
>                 "operation": "publish",
>                 "subject": "source rows",
>                 "visibility": "with_acquisition"
>               }
>             }
>           ]
>         },
>         "initial": "enumeration",
>         "changes": "observations",
>         "deletions": "unsupported",
>         "resume": "opaque_cursor",
>         "retentionMs": null,
>         "gap": "explicit_repair",
>         "limits": {
>           "http_response_bytes": "524288"
>         },
>         "restrictions": [],
>         "commands": {}
>       }
>     }
>   },
>   "occurrences": null,
>   "artifacts": {
>     "raw_archive": false,
>     "native_file_transfer_limit_bytes": null,
>     "external_versions": false,
>     "files": {}
>   },
>   "commands": {}
> }
> ```

**Recorded checks**

| Requirement | Scope | Evidence | Result |
| - | - | - | - |
| last-key-empty-page-ends | \{"kind":"collection","name":"records"} | Fixture: ./src/connectors/wfs/fixtures/first-page.json | passed (2026-10-24T21:36:12.453Z) |
| last-key-empty-page-ends | \{"kind":"collection","name":"records"} | Fixture: ./src/connectors/wfs/fixtures/continuation-page.json | passed (2026-10-24T21:36:12.453Z) |
| last-key-empty-page-ends | \{"kind":"collection","name":"records"} | Fixture: ./src/connectors/wfs/fixtures/empty-final-page.json | passed (2026-10-24T21:36:12.454Z) |
| last-key-empty-page-ends | \{"kind":"collection","name":"records"} | Fixture: ./src/connectors/wfs/fixtures/unfiltered-page.json | passed (2026-10-24T21:36:12.455Z) |
| page-publication-recovery | \{"kind":"collection","name":"records"} | Native test: integrations/acquisition/acquisition\_windows\_preserve\_sequences\_and\_restart\_fences\_old\_work (shared\_engine) | Execution result unavailable |
| identity-account | \{"kind":"connection"} | Fixture: ./src/connectors/wfs/fixtures/identity.json | passed (2026-10-24T21:36:12.457Z) |

Hosted qualification: **unestablished for this catalog configuration**. Installed connections report their own identity, authority and current status.

## Provider guidance

Compiled declaration examples and configuration details are published in the [connector reference](https://docs.bijection.com/integrations/connectors/index).

Setup: `endpoint` is the WFS service URL (for example
`https://maps.example.org/geoserver/wfs`) and is connection-owned; `typeName`
selects the feature type (`typeNames`). Install a `wfs` credential
(`wfs.credential(name)`); its deployment presentation (bearer, header or query
API key) authenticates requests. The connection check reads
`GetCapabilities` (`sections=ServiceIdentification`) through the host `xml`
codec and requires a `WFS_Capabilities` root naming a WFS service type.

One record per feature, keyed by `featureId`, the declared integer
`idProperty` read as an exact integer. The id must be published as a feature
property (GeoServer: expose primary keys); `gml:id` alone is not a key.
`geometry` is the GeoJSON geometry or `null`, published in the
WGS84 XY coordinate space (`WGS84_XY_SPACE`, sphere distances).

## What the declaration establishes

* `GetFeature` with `outputFormat=application/json` and
  `srsName=urn:ogc:def:crs:OGC:1.3:CRS84`, so axis order is longitude then
  latitude. Any reprojection is the server's; nothing is converted, repaired
  or reprojected here, and geometry the 2D profile refuses (3D positions, an
  uncut antimeridian edge) fails admission.
* A keyset walk: `sortBy=<id> ASC` with `count=<n>`, and from the second page
  a FES 2.0 `filter` `<id> > K`, where `K` is the host's last-record-key
  continuation. The value joined into the filter is the host's exact integer
  key, so it cannot alter the filter markup.
* `startIndex` is not used: it is an offset the guest would choose, which the
  host cannot verify, over an ordering an insert or delete shifts. A response's
  `next` link (the GML `next` attribute, or a GeoJSON `links` member some
  servers add) cannot be followed either: a records listing has no retained
  next-page capability; that capability is admitted only for traversal and
  resource listings.
* The reader refuses keys that are not strictly ascending after the
  continuation (a server without the Sorting conformance class, or one that
  ignored the filter), geometry of an undeclared type, and a page larger than
  `count`.

## What it does not establish

WFS has no change feed: this is a periodic re-walk of the current features,
never a change history. Coverage is `none`: a completed walk proves the values
each page returned at the moment it was read, is not a snapshot, and never
withdraws a feature it did not see. Server-side access rules and layer
filters narrow results silently.

A watermark mode over a timestamp property (`ResumeSource::MaximumField`) is
not provided. Its continuation lives within one pass, so each pass still starts
from the beginning and saves nothing over the id keyset; and because its bound
is inclusive and advances only when the page maximum grows, more than `count`
features sharing one timestamp end the pass early. Change-only polling needs a
position retained across passes, which the record-observation protocol does
not have.

GML output is not built. The `xml` codec decodes elements into declared
objects and never into numbers, so GML coordinates could only be retained as
text, not as a profile geometry, and GML's `next` paging is a provider URL the
records contract cannot follow. Hosted qualification against a real server has
not been run.

## Provider references

Provider references and prerequisites are maintained in the connector guidance above. No separate provider-documentation review date is recorded.

## Source and evidence

[Canonical connector source](https://github.com/bijectionhq/component-support/blob/b632604330ce9cbcfe17a5a680ef4fbe80f6f672/packages/connectors/src/connectors/wfs/README.md), [native analysis](https://github.com/bijectionhq/component-support/blob/b632604330ce9cbcfe17a5a680ef4fbe80f6f672/packages/connectors/contract-analysis.json) and [check receipts](https://github.com/bijectionhq/component-support/blob/b632604330ce9cbcfe17a5a680ef4fbe80f6f672/packages/connectors/evidence.json).

Connector artifact: `905888ea276a2a28e36981a79e8142b2547ea451c3e63162cb6915ad4a7d1305`.

The resource declaration examples above are compiled and compared with exact catalog declarations. Recorded checks apply only to their source, declaration and runtime identities. Configure a connection and inspect its status to establish deployment-specific readiness.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.