Versioning and Timestamps
Every DemandFlow object carries five fields that describe its change history. These are server-maintained and sufficient for most "when did this last change and who did it" questions without consulting an audit log.
The five fields
| Field | Set when | Value |
|---|---|---|
created | POST | Epoch ms at creation. Never changes. |
ownerId | POST | The user who created the object. Never changes. |
updated | POST and every PATCH | Epoch ms of the most recent write. |
updatedId | POST and every PATCH | The user behind the most recent write. |
_df_version | 0 on POST, +1 on every PATCH | Monotonically incrementing integer. |
Detecting changes
_df_version is the safest field to compare. Two reads of the same object that return the same _df_version are guaranteed to have identical content. Two reads with different versions definitely differ.
updated is fine for human display ("Last edited 5 minutes ago") but isn't safe to compare for change detection, two PATCHes within the same millisecond would share an updated value.
Optimistic concurrency
Read the object, note _df_version, send your PATCH. If another writer changed the object in between, your PATCH will still succeed (PATCH does not currently enforce a version condition) but the resulting _df_version will be your read value + 2 or more, signalling that an interleaved write happened. Decide your reconciliation policy based on that.
For workflows that need strict last-writer-wins protection, read the object after your PATCH and compare the returned _df_version to readVersion + 1.
What you cannot set yourself
The PATCH endpoint silently ignores attempts to change id, ownerId, or created. The server overwrites updated, updatedId, and _df_version with its own values regardless of what you send.
For full history
The five fields above tell you about the most recent change only. For a complete audit trail (every previous value, who changed each field, when), use the per-tenant audit log queryable via the LOG entity.