How do I maintain records for custom object types?
Quick answer
Section titled “Quick answer”In the Data module, you select the object type and click “Add record” — the form is generated automatically from the defined custom fields. For each record, you get History (with restore), Files, Relations, a search, and a JSON import with column mapping.
Prerequisites
Section titled “Prerequisites”The Flex platform requires Pro or higher (the custom_fields feature).
Also required: the object type already has
custom fields defined —
otherwise “Add record” stays disabled (“Add at least one field to this
type first.”).
Instructions
Section titled “Instructions”-
Choose a type. Open Data and click the object type chip. The table shows the records with their first few fields as columns; the search box (“Search records…”) filters across all values.
Screenshot pendingkatalog-datensaetze-01Data page with object type chips, a search box, and the record table with row actionsThe record table of an object type, with search and row actions. -
Create a record. Click “Add record”. The form shows exactly the defined custom fields — required fields are marked, select fields offer their configured options, and relation fields offer a record picker. Saving creates the entry; validation errors appear as a message in the form.
Screenshot pendingkatalog-datensaetze-02'Add record' form with fields generated automatically from the custom field definitionsThe form is generated automatically from the type's custom fields. -
Per row: History, Files, Relations, Edit, Delete. The icons at the end of the row open:
- History — every change as a timeline (Created/Updated/Deleted/ Restored) with the changed fields; older states can be brought back via “Restore”.
- Files — upload/download attachments (see Attachments).
- Relations — links to other records, split into Outgoing and
Incoming, with a freely choosable relation type (e.g.
depends_on).
Screenshot pendingkatalog-datensaetze-03History dialog of a record with a timeline of actions and the 'Restore' buttonThe history: every change traceable, older states restorable. -
Import. Via “Import”, you insert records as JSON rows, map the columns to fields (column mapping), optionally choose a field to match on (“Match by” — existing records are then updated instead of duplicated), and check the result via “Preview” before “Import” applies it.
-
Save views. Via “Save view”, you save the selected object type as a named view and jump straight back to it later with a single click.
Create — data contains the custom field values:
curl -X POST https://demo.notory.io/api/v1/records \ -H "Authorization: Bearer inv_dein_token" \ -H "Content-Type: application/json" \ -d '{ "object_type": "vehicle", "data": { "plate": "M-TT 2026", "fuel": "Elektro", "seats": 5 } }'{ "id": "7d2f4a90-1b3c-4e5d-8f6a-9c0b1d2e3f44", "object_type": "vehicle", "data": { "plate": "M-TT 2026", "fuel": "Elektro", "seats": 5 }, "created_at": "2026-07-08T11:20:41Z", "created_by": "b7c3…"}List and search — q searches the values; for large datasets, there’s
cursor-based pagination (limit + cursor from next_cursor):
curl -H "Authorization: Bearer inv_dein_token" \ "https://demo.notory.io/api/v1/records?object_type=vehicle&q=elektro&limit=50"Update and delete (deleting is a soft delete):
curl -X PUT https://demo.notory.io/api/v1/records/7d2f4a90-1b3c-4e5d-8f6a-9c0b1d2e3f44 \ -H "Authorization: Bearer inv_dein_token" \ -H "Content-Type: application/json" \ -d '{ "data": { "plate": "M-TT 2026", "fuel": "Elektro", "seats": 7 } }'curl -X DELETE -H "Authorization: Bearer inv_dein_token" \ https://demo.notory.io/api/v1/records/7d2f4a90-1b3c-4e5d-8f6a-9c0b1d2e3f44History and restoring:
curl -H "Authorization: Bearer inv_dein_token" \ https://demo.notory.io/api/v1/records/7d2f4a90-1b3c-4e5d-8f6a-9c0b1d2e3f44/historycurl -X POST -H "Authorization: Bearer inv_dein_token" \ https://demo.notory.io/api/v1/records/7d2f4a90-1b3c-4e5d-8f6a-9c0b1d2e3f44/restore/HISTORY_IDRelations:
curl -X POST https://demo.notory.io/api/v1/records/7d2f4a90-1b3c-4e5d-8f6a-9c0b1d2e3f44/links \ -H "Authorization: Bearer inv_dein_token" \ -H "Content-Type: application/json" \ -d '{ "to_record_id": "ZIEL_RECORD_ID", "relation_type": "depends_on" }'Bulk import with column mapping and upsert — check first with
dry_run=true:
curl -X POST "https://demo.notory.io/api/v1/records/import?dry_run=true" \ -H "Authorization: Bearer inv_dein_token" \ -H "Content-Type: application/json" \ -d '{ "object_type": "vehicle", "rows": [ { "Kennzeichen": "M-TT 2027", "Antrieb": "Diesel" } ], "mapping": { "Kennzeichen": "plate", "Antrieb": "fuel" }, "key_field": "plate" }'Possible errors: 403 (plan below Pro), 404 (a record that isn’t
yours or doesn’t exist), 422/400 (custom field validation — the response
names the affected fields).
What happens behind the scenes?
Section titled “What happens behind the scenes?”- Validation against custom fields: Every write is checked against the object type’s definitions (type, options, required fields). Errors are returned per field and appear in the interface as a form message.
- Automatic history: Notory writes a history entry for every action
(
created,updated,deleted,restored), along with the data snapshot and the user responsible — this is the basis for the timeline and for restoring. - Soft delete: Deleted records are marked as deleted (“Record moved to trash”), not removed immediately.
- Import as upsert: With
key_field, the import matches on the chosen field and updates matches instead of creating duplicates; the preview (dry_run) reports created/updated/error counts per row, without writing anything. - Audit field pair:
created_by/updated_byand the timestamps are maintained automatically. - Tenant isolation: Records, history, links, and attachments are strictly limited to your tenant.
Related topics
Section titled “Related topics”- Create an object type
- Define custom fields
- Scan & Stocktake — find and count records by code
- Attachments — the file dialog in detail