Skip to main content

Event Types

The eventTypes array on a subscription is where you say what you actually want to hear about. Each entry is an independent rule; a subscription fires if any of its event types matches.

The Two Event Types​

Agility records every asset creation and every asset change. Each event type entry declares which of the two it is watching:

typeFires when
AssetCreatedAn asset of from is created.
AssetChangedAn asset of from is modified.

These are the only two accepted values. Anything else is rejected at subscription-create time with a message naming both.

Fields​

FieldTypeRequiredDescription
typestringyesAssetCreated or AssetChanged.
fromstringyesThe asset type to watch, e.g. Story. Use the system name — see terminology.
attributesstring[]noRestrict to changes touching these attributes. Omit to fire on any change.
filterstring[]noFilter expressions the asset must satisfy. The full filter language — operators, value lists, unary existence and grouping all work here.
withobjectnoFilter context — variable bindings substituted into filter.
userContextstringnoOid token of a member whose visibility the event is evaluated under.
selectarraynoAttribute paths to project into the delivered payload's snapshot.

Building up an Event Type​

Every Change to a Story​

{
"type": "AssetChanged",
"from": "Story"
}

Only When Status Changes​

attributes narrows the rule to changes that touch the listed attributes. Without it you are notified of any change to the asset, which on a busy instance is a lot of traffic.

{
"type": "AssetChanged",
"from": "Story",
"attributes": ["Status"]
}

Only Stories in One Project​

filter takes the same filter expressions as a query, and with binds the variables they reference. Keeping the value in with rather than inlining it makes the subscription easy to retarget later.

{
"type": "AssetChanged",
"from": "Story",
"attributes": ["Status"],
"filter": ["Scope=$Scope"],
"with": {
"$Scope": "Scope:0"
}
}

See the query grammar reference for the full filter syntax.

Only What a Particular Member Can See​

Most assets in Agility are secured by their relationship to a Scope (project). Without userContext, an event type sees everything — assets in every project, regardless of who can normally view them.

userContext runs the evaluation as a specific member, so only changes visible to that member produce events:

{
"type": "AssetChanged",
"from": "Story",
"attributes": ["Status"],
"userContext": "Member:1002"
}
warning
userContext is a security control, not a convenience

An event type without userContext will happily deliver data from projects the subscription's creator could not otherwise read, to whatever URL you named. If the receiving system is not trusted with instance-wide data, set userContext to a member with appropriately limited visibility.

Note also that the original reference material contained the literal value "Memeber:1002" in two of its examples — a misspelling of Member. An unresolvable Oid token here does not fail open in a useful way; use the correct spelling.

Include Asset Details in the Delivery​

By default the delivered payload identifies the asset by Oid and lists what changed, but tells you nothing else about it. select projects additional attributes into the payload's snapshot, using the same projection syntax as a query — including dot traversal across relations:

{
"type": "AssetChanged",
"from": "Story",
"attributes": ["Status"],
"filter": ["Scope=$Scope"],
"with": {
"$Scope": "Scope:0"
},
"select": ["Name", "Owners.Name"]
}

The snapshot in the delivered payload then carries Name and each owner's Name, in the same shape a query.v1 result would have. This is what lets a handler act on an event without calling back into the API for context — worth doing, because it removes a round-trip and avoids a race where the asset changes again before you read it.

note
The field is attributes, plural

A common mistake is sending attribute (singular). Because api/webhook rejects unknown keys instead of ignoring them, that produces a 400 rather than a silent misconfiguration. See unknown keys are rejected on the create page for the mechanism.

A Complete eventTypes Array​

Event types compose. This subscription fires on new Defects anywhere, and on Story status changes in one project:

{
"eventTypes": [
{
"type": "AssetCreated",
"from": "Defect",
"select": ["Name", "Number", "Priority"]
},
{
"type": "AssetChanged",
"from": "Story",
"attributes": ["Status"],
"filter": ["Scope=$Scope"],
"with": { "$Scope": "Scope:0" },
"select": ["Name", "Status.Name", "Owners.Name"]
}
]
}

Each delivered event names the eventType that produced it, so a handler can dispatch on it.