Skip to main content

Updating Assets

An update command is a command object with a from clause and an update clause. from selects the target — either a single OID token or an asset type narrowed by where or filter.

Updating a Single Asset​

{
"from": "Story:1585",
"update": {
"Name": "Update members",
"Description": "Given I am an admin, when I open a member's profile, I can edit fields."
}
}
Response
{
"assetsCreated": { "oidTokens": [], "count": 0 },
"assetsModified": { "oidTokens": ["Story:1585"], "count": 1 },
"assetsOperatedOn": { "oidTokens": [], "count": 0 },
"commandFailures": { "commands": [], "count": 0 },
"queryResult": { "results": [], "count": -1 }
}

Updating Everything That Matches a Query​

Give from an asset type and add a where (attribute equality) or filter (full query.v1 filter expression) clause — with variables work in the filter here exactly as they do in a query, arrays included. Every matching asset receives the same update.

{
"from": "Workitem",
"where": { "Parent": "Story:1591" },
"update": {
"Owners": ["Member:20", "Member:1575"]
}
}
Response
{
"assetsModified": { "oidTokens": ["Task:1592", "Test:1593"], "count": 2 }
}
There is no implicit limit

from: Story with no where matches every Story the calling identity can see. Use preview mode to see exactly which assets a query-scoped update will touch before you run it.

Scalar and Single-Value Relation Attributes​

Scalars and single-value relations use the same syntax — assign the value directly. A single-value relation accepts an OID token or a name, optionally qualified with a path; the name must resolve to exactly one asset.

{
"from": "Task:1489",
"update": {
"Description": "TODO -- get details from Andre Agile",
"Status": "In Progress"
}
}

Internally both are projected into the same add / remove shape used for multi-value relations. That normalisation is visible in preview mode:

[
{
"@526e8128-41be-44ef-8401-bb3bd19b03ef": {
"oid": "Task:1489",
"update": {
"Description": { "add": ["TODO -- get details from Andre Agile"], "remove": [] },
"Status": { "add": ["In Progress"], "remove": [] }
}
}
}
]

The projection does not distinguish scalar from relation. The processing phase resolves the attribute definition and applies the value appropriately.

For multi-value relations, the add / remove structure becomes meaningful and gains several convenience forms — see Updating multi-value relations.

Reordering with The Order Attribute​

Order is a Rank attribute, and rank attributes work differently from every other type in two ways that matter.

Never read a rank value — sort by it

The value of a rank attribute is an opaque token whose only meaning is relative to other ranks. It is not a position, not an index, and not a number you can reason about. Reading it, storing it, comparing it arithmetically or trying to compute a "next" value will all mislead you, and the representation is free to change.

The supported way to consume ordering is to sort by the attribute and take the sequence you get back:

from: Story
where:
Scope: Scope:1000
sort:
- +Order

This applies to every Rank attribute, not just Story.Order. Most asset types have one — Defect.Order, Epic.Order, Issue.Order, and an Order on nearly every list type, which is what drives the sequence of values in a dropdown.

Writing follows the same principle: you do not assign a rank, you name a neighbour. The Order attribute takes a positional object rather than a value, identifying the sibling the asset should sit before or after.

Both Before and After are supported, and each takes the OID token of a sibling.

Move Story B before Story A
from: Story:1002
update:
Order:
Before: Story:1001
Move Story C after Story D
{
"from": "Story:1003",
"update": {
"Order": { "After": "Story:1004" }
}
}

Verify with a sorted query:

from: Story
where:
Scope: Scope:1000
sort:
- +Order

Updating a Deleted Asset​

Deleted assets are excluded from queries by default. To target one, add IsDeleted: true to the where clause — even when from is an explicit OID token.

from: Story:1591
where:
IsDeleted: true
update:
Owners: Member:20

The update succeeds and is reported in assetsModified as normal. The asset remains deleted.

The same rule applies to operations — Undelete needs IsDeleted: true to find its target.

Recording a Change Comment​

Include ChangeComment inside the update node to attach an audit comment to the change:

{
"from": "Story:1024",
"update": { "Estimate": "5", "ChangeComment": "Re-estimated after grooming" }
}

ChangeComment is not stored as an attribute — it becomes the change's audit comment, read back from history as ChangeComment. On a create command it goes at the command root instead, alongside AssetType (see creating assets).

Omit it and the change is stamped Modified through api/asset (creates get Created through api/asset). The default distinguishes Bulk API writes from UI edits in the audit trail; rest-1.v1 stamps nothing.

Unknown Attributes​

Naming an attribute that does not exist on the target asset type produces a command failure, not an HTTP error. The snippet below shows only the commandFailures member of the response — the full envelope still carries assetsCreated, assetsModified, assetsOperatedOn and queryResult alongside it, as shown at the top of this page:

commandFailures (other response members omitted)
{
"commands": [
{
"@update": {
"oid": "Scope:0",
"update": { "MuddleBubble": { "add": ["BubbleMuddle"], "remove": [] } }
},
"error": {
"message": "Unknown AttributeDefinition: Scope.MuddleBubble",
"sourceCommandIndex": 0
}
}
],
"count": 1
}

See Errors and partial failures for the full failure model.