diff --git a/docs/reference/client.md b/docs/reference/client.md index 2c663a1..387a0a5 100644 --- a/docs/reference/client.md +++ b/docs/reference/client.md @@ -447,3 +447,37 @@ Two responses are worth recognising by shape: Both shapes, and the rules behind them, are in [External ids & naming](./external-ids). + +### Unknown fields are refused {#unknown-fields} + +A request body naming a field the endpoint does not have is a `400`, not a silent success. A +typo, or a field that has since been retired, would otherwise be dropped and answered `200`, +telling you a change was applied when nothing happened. The body is an +[RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem document of +`type: ".../errors/unreadable-request-body"`, with one `errors` entry per offender, each +located by a JSON Pointer and listing the names accepted at that position: + +```json +{ + "type": "https://intellistream.ai/errors/unreadable-request-body", + "title": "Bad Request", + "status": 400, + "detail": "Unknown field: eventTime", + "errors": [ + { + "detail": "Unknown field", + "pointer": "#/items/0/update/eventTime", + "allowedFields": ["dataSetId", "description", "externalId", "metadata", + "relatedResources", "source", "status", "subType", "type"] + } + ] +} +``` + +Every offender in the body is reported at once, at whatever depth it sits, so several stale +fields cost one round trip rather than one each. A body that cannot be parsed at all, +malformed JSON or a value of the wrong shape, answers with the same `type` and a `detail` +naming the problem, plus `line` and `column` where the parser can say. + +The clients only ever send fields they declare, so this reaches you when you build a body by +hand, or keep an old field name in one. diff --git a/docs/reference/datasets.md b/docs/reference/datasets.md index 0bcd83e..60b5f3f 100644 --- a/docs/reference/datasets.md +++ b/docs/reference/datasets.md @@ -157,8 +157,9 @@ let matches = api.datasets.filter(&DatasetFilter::from_filter(criteria)).await?; :::note There is no `writeProtected` or `deactivated` -Both were removed server-side as inert. The api drops unknown keys silently, so a filter still -carrying one looked like it was narrowing and was not. +Both were removed server-side as inert. A filter or a create still carrying either is refused +as an [unknown field](./client#unknown-fields), so a stale client fails on the first call +rather than filtering on nothing. ::: ## Search {#search} diff --git a/docs/reference/events.md b/docs/reference/events.md index c96f1b0..550128c 100644 --- a/docs/reference/events.md +++ b/docs/reference/events.md @@ -56,8 +56,8 @@ HTTP caller should expect the quotes. `relatedResources` replaced a `relatedResourceIds` / `relatedResourceExternalIds` pair. The two were independent inputs and drifted: a mismatched pair was unioned into an event describing both resources, and a patch setting only the external ids left the stored ids stale. There are no -aliases, and events ignore unknown properties, so a client still sending the old field names gets -a `200` with its relations silently dropped. Java SDK users get a compile break on the removed +aliases: a client still sending the old field names is refused with a `400` naming them as +[unknown fields](./client#unknown-fields). Java SDK users get a compile break on the removed setters instead. Supply an `id`, an `externalId`, or both. The server resolves whichever side you left out and