Endpoints — Records, POST
Every call in this family: what the card records, the edge cases that live on the call, and the verdict of every entry that measured it. Each of those lines names the door holding that entry's rules. The map is corpus/INDEX.md.
POST /entity/<type>
project is the requirement on every project-scoped type and the identity field is not, whatever the schema says. ?fields is ignored, and the 201 returns the whole record.
Omitting the identity field is not an error: the server writes
New Shot <id>and returns 201. Nothing is unique, so a re-run of an ingest doubles the rows rather than failing.?fields=codereturns 10 attribute keys, not one. Every write ignores it, so re-read the row when you need a dotted path or a narrowed set.An unknown field is a 400 here, unlike an unknown
fieldsname on a read, which is dropped at- Writes are loud about names; reads are silent.
created_atcomes back as2026-09-04 03:51:48 UTC, space separated, where a read returns2026-09-04T03:51:48Z. The same instant in two formats depending on the call.
Measured by
060_entity_dict_name(findings) — Thenamein an entity dict is the target'scached_display_name, filled on every type measured, single and multi alike. Read it, not the per-type identity field, and expect decoration.
rules:doors/findings-read011_create_project(findings) — A script user can create a Project with nothing but {"name": ...}, at 201, but the response echoes only 6 attributes, so read the project back if you need anything else.
rules:doors/findings-write012_create_version(findings) — The schema's mandatory flags are not the create contract: on every project-scoped type measured,projectis required and the identity field is optional, server-generated and not unique.
rules:doors/findings-write024_read_after_write(findings) — Every write ignores ?fields. A create returns what you sent plus the server defaults, an update returns the whole record, and neither resolves a dotted path, so re-read for those and after an upload.
rules:doors/findings-write058_local_storage_roots(findings) — One create fills everylocal_path_*the storage row defines, whichever platform's root the path was under. The server picks the deepest matching root, and no conditional-write header is honoured.
rules:doors/findings-write069_client_note(findings) —client_notecannot be set over REST:trueon create is 400 and anyPUTis 400editable on create only.sg_note_type: "Client"is the one marker a caller can write.
rules:doors/findings-write070_authored_timestamps(findings) — A create body sets created_at and updated_at and they read back exactly, on Note, Task and Version, though the schema flags both editable false; every PUT on either 400s.
rules:doors/findings-write025_event_log(findings) — meta.old_value and meta.new_value answer "what was this before", but meta is unfilterable and unsortable: narrow on entity, event_type and attribute_name, sort -id, read meta yourself.
rules:doors/findings-observe049_script_events(findings) — A script's writes reach the event log only while its ApiUser has generate_event_log_entries True. The default is False and nothing errors when off. One create logs one row per field plus one _New.
rules:doors/findings-observe067_notes_in_the_stream(findings) — A Reply reaches every linked stream in 33 s ascreate_reply, creates too; a script's Note create and status changes were absent after 430 s. Write as a person.
rules:doors/findings-observe001_publish_version_with_media(recipes) — Publish a generated image to Flow PT as a Version, with provenance and the workflow attached
rules:doors/recipes004_register_published_file(recipes) — Register the next PublishedFile without overwriting the last one, and write a path the server resolves for every platform
rules:doors/recipes007_build_and_reconcile_a_cut(recipes) — Write a Cut and its CutItems from an edit, read the timeline back, and reconcile a second edit against the Cut already there
rules:doors/recipes008_delivery_progress(recipes) — Keep a Delivery honest about what a long transfer is doing, including when it is cancelled and when it crashes
rules:doors/recipes013_publish_file_bytes(recipes) — Publish a file's bytes onto a PublishedFile when the caller has no LocalStorage root to write under
rules:doors/recipes
Silent on this call
post_entity_type—projectis the requirement on every project-scoped type and the identity field is not, whatever the schema says.?fieldsis ignored, and the 201 returns the whole record.024_read_after_write— Every write ignores ?fields. A create returns what you sent plus the server defaults, an update returns the whole record, and neither resolves a dotted path, so re-read for those and after an upload.058_local_storage_roots— One create fills everylocal_path_*the storage row defines, whichever platform's root the path was under. The server picks the deepest matching root, and no conditional-write header is honoured.025_event_log— meta.old_value and meta.new_value answer "what was this before", but meta is unfilterable and unsortable: narrow on entity, event_type and attribute_name, sort -id, read meta yourself.049_script_events— A script's writes reach the event log only while its ApiUser has generate_event_log_entries True. The default is False and nothing errors when off. One create logs one row per field plus one _New.067_notes_in_the_stream— A Reply reaches every linked stream in 33 s ascreate_reply, creates too; a script's Note create and status changes were absent after 430 s. Write as a person.
corpus/endpoints/post_entity_type.md
POST /entity/<type>/<id>
Revives a retired row. ?revive=1 is required and any JSON body is discarded, so this is not an update via POST.
| you send | result |
|---|---|
?revive=1, ?revive=true, ?revive=yes |
revived |
?revive=0, ?revive=false |
400 revive must be true |
no revive parameter |
400 revive is missing |
| a body of field values | 200, the fields are not applied |
?fields=code |
200, no attributes returned either way |
The response has no
attributeskey at all, which is thinner than any other write returns. Re-read the id to see the record.Field values survive the retire and come back with the revive. Nothing is reset.
did_revive: falseat 200 is the only signal that the row was already live. Readmeta, not the status code.
Measured by
048_one_record_beyond_crud(findings) — POST on one record is revive, not update:?revive=1is required and the body is ignored./<field>reads image and attachment fields only, andrelationships/<field>is the same data, unpaged.
rules:doors/findings-read
Silent on this call
048_one_record_beyond_crud— POST on one record is revive, not update:?revive=1is required and the body is ignored./<field>reads image and attachment fields only, andrelationships/<field>is the same data, unpaged.
corpus/endpoints/post_entity_type_id.md
POST /entity/_batch
The key is requests, not data, and sending data is 400 requests is missing. It answers 200 rather than 201, and one bad request rolls the whole batch back.
It is atomic. The Shot the first request would have created does not exist after the 404.
The response nesting is the trap that outlives a run. Reading
row["id"]instead ofrow["data"]["id"]yieldsNone, so cleanup silently skips the rows and they stay on the site.A returned id does not by itself prove the row exists. Read back after a batch that matters.
The request key and the response key differ by name.
requestsin,dataout.
Measured by
028_loud_and_silent(findings) — A 400 is trustworthy and usually names the legal set, but a 200 proves nothing: an unknown field, sort key or query param is a no-op, and a batch can return an id for a row it never made.
rules:doors/findings-protocol024_read_after_write(findings) — Every write ignores ?fields. A create returns what you sent plus the server defaults, an update returns the whole record, and neither resolves a dotted path, so re-read for those and after an upload.
rules:doors/findings-write002_batch(recipes) — Apply many creates, updates and deletes in one atomic call, and match the results back to the requests
rules:doors/recipes005_propagate_status(recipes) — Roll a status up from a parent's Tasks and Versions onto the parent, without racing a concurrent write
rules:doors/recipes007_build_and_reconcile_a_cut(recipes) — Write a Cut and its CutItems from an edit, read the timeline back, and reconcile a second edit against the Cut already there
rules:doors/recipes001_batch_create_skips_validation(reports) — A create inside POST /entity/_batch skips the required-attribute validation the single-create path applies, and answers 200 with the id of a row no read can reach.
rules:doors/reports
Silent on this call
post_entity_batch— The key isrequests, notdata, and sendingdatais 400requests is missing. It answers 200 rather than 201, and one bad request rolls the whole batch back.028_loud_and_silent— A 400 is trustworthy and usually names the legal set, but a 200 proves nothing: an unknown field, sort key or query param is a no-op, and a batch can return an id for a row it never made.024_read_after_write— Every write ignores ?fields. A create returns what you sent plus the server defaults, an update returns the whole record, and neither resolves a dotted path, so re-read for those and after an upload.002_batch— Apply many creates, updates and deletes in one atomic call, and match the results back to the requests005_propagate_status— Roll a status up from a parent's Tasks and Versions onto the parent, without racing a concurrent write
corpus/endpoints/post_entity_batch.md