21  Notes

11 operations.

21.0.1 listDatasetNotes

GET /api/datasets/{slug}/notes

Lists the notes on one dataset.

Why it exists. ‡ List the location notes pinned to a dataset, each with a time-limited link to its attached PDF, for the notes panel.

Called by — modules/photo-map-3d/overlays/hooks/use-notes-fetching.ts · modules/photo-map-3d/overlays/hooks/use-notes-management.ts

Reached from — /datasets/<slug> · /w/data-explorer/anomalies/map · /w/data-explorer/assets · /w/integrity/assets · /w/integrity/evidence-explorer

Lists all location notes for a dataset (RLS-scoped), newest first, with fresh 1-hour signed URLs for attached PDFs.

Authentication: CookieAuth, SupabaseAuth

Returns — notes · count

Field names as the handler returns them; the source states no types for them.

Effect — reads datasets · location_notes

Parameters

Name In Required Type Notes
slug path yes string

Responses

Status Meaning Body
200 Notes. LocationNote
401 Unauthorized. Error
404 Dataset not found. Error
500 Failed to fetch notes. Error

21.0.2 createDatasetNote

POST /api/datasets/{slug}/notes

Creates a note on a dataset.

Why it exists. ‡ Pin an observation to a place in a dataset, so a field or desk observation is recorded against the imagery rather than in someone’s notebook.

Called by — app/(authenticated)/w/integrity/actions/actions-client.tsx · components/create-note-dialog.tsx · modules/photo-map-3d/overlays/components/add-note-dialog.tsx · modules/photo-map-3d/ui/components/inspector-sections/add-note-inspector-section.tsx …and 1 more

Reached from — /datasets/<slug> · /w/data-explorer/anomalies/map · /w/data-explorer/assets · /w/data-explorer/insights · /w/integrity/actions · /w/integrity/assets …and 1 more

Creates a location note on the dataset, owned by the calling user.

Authentication: CookieAuth, SupabaseAuth

Returns — note

Field names as the handler returns them; the source states no types for them.

Effect — writes (insert) datasets · location_notes

Parameters

Name In Required Type Notes
slug path yes string

Request body

Field Type Required
note_text string yes
latitude number, nullable no
longitude number, nullable no
altitude number, nullable no
color string no
tag_id string, nullable no
metadata object no

Responses

Status Meaning Body
201 Created note. LocationNote
400 Missing required field note_text. Error
401 Unauthorized. Error
404 Dataset not found. Error
500 Failed to create note. Error

21.0.3 getDatasetNote

GET /api/datasets/{slug}/notes/{noteId}

Opens one note (with a fresh one-hour link to its PDF, if any).

Why it exists. ‡ Fetch one location note and a time-limited link to its PDF attachment.

Fetches one note (looked up by id; the slug segment is not validated), adding a 1-hour signed PDF URL when a PDF is attached.

Authentication: CookieAuth, SupabaseAuth

Returns — note

Field names as the handler returns them; the source states no types for them.

Effect — reads datasets · location_notes

Parameters

Name In Required Type Notes
slug path yes string
noteId path yes string

Responses

Status Meaning Body
200 Note. LocationNote
401 Unauthorized. Error
404 Note not found. Error
500 Internal server error. Error

21.0.4 updateDatasetNote

PATCH /api/datasets/{slug}/notes/{noteId}

Edits a note (creator or an admin of its organization).

Why it exists. ‡ Edit a location note’s text or position — the person who wrote it, or an admin of the note’s organization moderating on their behalf.

Called by — app/(authenticated)/w/integrity/actions/actions-client.tsx · components/notes/hooks/use-notes-data.ts · modules/photo-map-3d/core/hooks/use-click-handlers.ts · modules/photo-map-3d/overlays/hooks/use-notes-management.ts …and 2 more

Reached from — /datasets/<slug> · /w/data-explorer/anomalies/map · /w/data-explorer/assets · /w/data-explorer/insights · /w/integrity/actions · /w/integrity/assets …and 1 more

Partially updates a note; the creator, or an admin of the note’s organization, may edit. Only provided fields are written; PDF fields cannot be changed here. Returns the updated row unwrapped (not inside a note envelope).

Authentication: CookieAuth, SupabaseAuth

Returns — not readable from the source: the handler returns a value assembled at run time rather than a literal.

Effect — writes (update) datasets · location_notes

Parameters

Name In Required Type Notes
slug path yes string
noteId path yes string

Request body

Field Type Required
note_text string no
latitude number, nullable no
longitude number, nullable no
altitude number, nullable no
color string no
tag_id string, nullable no
metadata object no

Responses

Status Meaning Body
200 Updated note (top-level row). LocationNote
401 Unauthorized. Error
403 Only the note’s creator or an admin of its organization may edit it. Error
404 Note not found. Error
500 Failed to update note. Error

21.0.5 deleteDatasetNote

DELETE /api/datasets/{slug}/notes/{noteId}

Deletes a note and its attachment (creator or an admin of its organization).

Why it exists. ‡ Delete a location note and any PDF attached to it — the person who wrote it, or an admin of the note’s organization moderating on their behalf.

Called by — components/notes/hooks/use-notes-data.ts · modules/photo-map-3d/ui/components/inspector-sections/note-inspector-section.tsx · modules/photo-map-3d/ui/components/mobile/mobile-inspector-panel.tsx

Reached from — /datasets/<slug> · /w/data-explorer/anomalies/map · /w/data-explorer/assets · /w/data-explorer/insights · /w/integrity/assets · /w/integrity/evidence-explorer

Deletes a note and (best-effort) its attached PDF blob; the creator, or an admin of the note’s organization, may delete it.

Authentication: CookieAuth, SupabaseAuth

Returns — success · message

Field names as the handler returns them; the source states no types for them.

Effect — writes (delete) datasets · location_notes

Parameters

Name In Required Type Notes
slug path yes string
noteId path yes string

Responses

Status Meaning Body
200 Deleted.
401 Unauthorized. Error
403 Only the note’s creator or an admin of its organization may delete it. Error
404 Note not found. Error
500 Failed to delete note. Error

21.0.6 uploadDatasetNotePdf

POST /api/datasets/{slug}/notes/{noteId}/pdf

Attaches (or replaces) a PDF on a note — PDF only, up to 50 MB (creator or an admin of its organization).

Why it exists. ‡ Attach a PDF to a location note, or replace the one already there, so a note can carry the report or drawing it refers to.

Called by — components/create-note-dialog.tsx · components/notes/hooks/use-notes-data.ts · modules/photo-map-3d/overlays/components/add-note-dialog.tsx · modules/photo-map-3d/ui/components/inspector-sections/add-note-inspector-section.tsx …and 1 more

Reached from — /datasets/<slug> · /w/data-explorer/anomalies/map · /w/data-explorer/assets · /w/data-explorer/insights · /w/integrity/assets · /w/integrity/evidence-explorer

Uploads (or replaces) the PDF attachment for a note; the creator, or an admin of the note’s organization, may upload. PDF only, max 50 MB. Stored in the location-notes bucket at {dataset-slug}/notes/{noteId}/{filename}.

Authentication: CookieAuth, SupabaseAuth

Uses a service-role client (row-level security bypassed).

Returns — note · message

Field names as the handler returns them; the source states no types for them.

Effect — writes (update) datasets · location_notes

Parameters

Name In Required Type Notes
slug path yes string
noteId path yes string

Request body

Field Type Required
file string (binary) yes

Responses

Status Meaning Body
200 Updated note with signed PDF URL. LocationNote
400 No file, wrong MIME type, or file too large. Error
401 Unauthorized. Error
403 Only the note’s creator or an admin of its organization may upload. Error
404 Note or dataset not found. Error
500 Upload or note update failed. Error

21.0.7 deleteDatasetNotePdf

DELETE /api/datasets/{slug}/notes/{noteId}/pdf

Removes a note’s PDF attachment (creator or an admin of its organization).

Why it exists. ‡ Remove the PDF attached to a location note, leaving the note itself in place.

Called by — components/notes/hooks/use-notes-data.ts

Reached from — /w/data-explorer/insights

Removes the PDF attachment from a note and deletes the blob; the creator, or an admin of the note’s organization, may remove it. A storage delete failure is fatal (500) and leaves the note unchanged.

Authentication: CookieAuth, SupabaseAuth

Uses a service-role client (row-level security bypassed).

Returns — note · message

Field names as the handler returns them; the source states no types for them.

Effect — writes (update) datasets · location_notes

Parameters

Name In Required Type Notes
slug path yes string
noteId path yes string

Responses

Status Meaning Body
200 Updated note with PDF fields cleared. LocationNote
401 Unauthorized. Error
403 Only the note’s creator or an admin of its organization may delete. Error
404 Note not found, or note has no PDF attached. Error
500 Failed to delete PDF. Error

21.0.8 listNoteTags

GET /api/note-tags

List an organisation’s note vocabulary — the tags that say what kind of note something is.

Why it exists. † Offer the note vocabulary an organisation has curated, so a note can be typed as a work order, an observation or whatever else that customer names — from a controlled list rather than free text nothing downstream can read.

Called by — components/create-note-dialog.tsx · components/notes/components/edit-note-dialog.tsx · components/notes/hooks/use-notes-data.ts

Reached from — /w/data-explorer/insights

Reads note_tags scoped to the caller’s organisations via row-level security, for a picker. Retired tags are excluded unless includeRetired is set. organizationId narrows to one organisation but cannot widen what row-level security has already decided is visible.

Authentication: SupabaseAuth, CookieAuth

Returns — tags

Field names as the handler returns them; the source states no types for them.

Effect — reads note_tags

Parameters

Name In Required Type Notes
includeRetired query no string — one of true, false
organizationId query no string

Responses

Status Meaning Body
200 The tags the caller’s organisations have curated.
401 Not signed in. Error
500 The database refused the read or write for a reason the route could not classify. Error

21.0.9 createNoteTag

POST /api/note-tags

Name a kind of note this organisation’s vocabulary does not yet contain.

Why it exists. † Let an organisation name a kind of note its vocabulary does not yet contain, so the platform fits how that customer works instead of a fixed list.

Inserts a new tag into an organisation’s note vocabulary. Requires editor access to that organisation (403 otherwise); slug must be lower snake_case, and a live tag in the organisation may not already use that slug or label (409).

Authentication: SupabaseAuth, CookieAuth

Returns — tag

Field names as the handler returns them; the source states no types for them.

Effect — writes (insert) note_tags

Request body

Field Type Required
organization_id string yes
slug string yes
label string yes
description string no
color string no

Responses

Status Meaning Body
201 The tag as stored.
400 A missing field, or a slug that is not lower snake_case. Error
401 Not signed in. Error
403 Editor access to that organisation is required. Error
409 A live tag in this organisation already uses that slug or label. Error
500 The database refused the read or write for a reason the route could not classify. Error

21.0.10 updateNoteTag

PATCH /api/note-tags/{id}

Rename a note tag, or retire one that should no longer be offered. The slug cannot be changed.

Why it exists. † Rename a note tag, or retire one that should no longer be offered, so a customer’s vocabulary can be corrected and pruned without breaking the export mappings written against it or the notes already filed under it.

Renames a tag’s label, or changes its description or colour, or retires/reinstates it — a retired tag is simply no longer offered; notes already carrying it are unaffected. The slug itself can never be changed. Requires editor access to the tag’s organisation; a tag the caller cannot edit, or that does not exist, returns 404.

Authentication: SupabaseAuth, CookieAuth

Returns — tag

Field names as the handler returns them; the source states no types for them.

Effect — writes (update) note_tags

Parameters

Name In Required Type Notes
id path yes string

Request body

Field Type Required
label string no
description string, nullable no
color string, nullable no
retired boolean no

Responses

Status Meaning Body
200 The tag as stored.
400 An invalid id, an empty label, nothing to change, or an attempt to change the slug. Error
401 Not signed in. Error
404 No such tag, or the caller has no editor access to it. Error
409 Another live tag in this organisation already uses that label. Error
500 The database refused the read or write for a reason the route could not classify. Error

21.0.11 listNotes

GET /api/notes

Lists all location notes you can see, across datasets.

Why it exists. ‡ List every location note across all datasets the caller may see, so notes can be reviewed as a single worklist rather than dataset by dataset.

Called by — components/notes/hooks/use-notes-data.ts

Reached from — /w/data-explorer/insights

All location notes across datasets the caller can see (RLS-scoped via an inner join on datasets), newest first, with 1-hour signed URLs for attached PDFs. No pagination.

Authentication: CookieAuth, SupabaseAuth

Returns — notes · count

Field names as the handler returns them; the source states no types for them.

Effect — reads location_notes · organization_members

Responses

Status Meaning Body
200 Notes with their dataset. LocationNote
401 Unauthorized. Error
500 Failed to fetch notes. Error