Skip to main content

Watch (api/watch)

Manages the calling member's asset subscriptions — "watching" an asset so they are notified about it.

Everything here is scoped to the authenticated member. There is no parameter for acting on another member's watches, and the list endpoint returns only your own.

Not the same thing as webhooks

api/watch is per-member notification within Agility. Webhooks are instance-level HTTP callbacks to an external system. They share the word "subscription" and nothing else.

All routes require authentication.

Subscribe or Unsubscribe​

POST ~/api/watch
Content-Type: application/json

{ "oid": "Story:1234", "action": "Subscribe" }
FieldRequiredDescription
oidyesOID token of the asset to watch or unwatch
actionyesSubscribe or Unsubscribe

action is matched case-insensitively, so subscribe, Subscribe and SUBSCRIBE all work.

Response​

{ "oid": "Story:1234", "isWatching": true, "action": "subscribe" }

Note the echoed action comes back lower-case regardless of how you sent it. Do not round-trip it into a case-sensitive comparison.

isWatching is true after a subscribe and false after an unsubscribe.

Errors​

All are 400. The validation wording varies between versions — key on the status code and the missing field, not on the message text:

BodyCause
"Missing request body"No body sent
A ModelState objectoid or action missing — both are [Required]
"Invalid action"action is null, or is neither Subscribe nor Unsubscribe

Check One Asset​

GET ~/api/watch?oid=Story:1234
{ "oid": "Story:1234", "isWatching": false }

Returns 400 with "Missing oid" when the parameter is present but blank (?oid=). Omitting the parameter entirely returns 405 instead — a GET with no query routes against the POST-only subscribe endpoint.

List Everything Watched​

GET ~/api/watch/list
{ "watchedOids": ["Story:1234", "Defect:5678"] }

The watched OIDs for the calling member. Note the array is wrapped in an object rather than returned bare.

What a Subscribe Actually Creates​

A watch is not hidden state — it is ordinary assets, and api/watch is a convenience that assembles them so you don't have to know the machinery. A subscribe creates:

  • a Subscription — Name is a generated title ("Watching Logon (S-01001)"), EventDefinition is the watched type's changed event (Story.Changed), Subscriber is the calling member;
  • a SubscriptionTerm in its FilterTerms — AttributeToken: "ID", Value the watched OID — created in the subscription's context so its required pieces default correctly.

Both are queryable:

{
"from": "Subscription",
"select": ["Name", "EventDefinition", "FilterTerms.AttributeToken", "FilterTerms.Value"],
"where": { "Subscriber": "Member:20" },
"page": { "size": 50, "start": 0 }
}

Unsubscribing removes them again.

Two consequences worth knowing:

  • Watches are the narrow case of a wider model: the application's subscription editor composes SubscriptionTerms over attributes such as Scope.ParentMeAndUp, Owners, Status and Team against any event definition — richer subscriptions than a single-asset watch.
  • Building the same assets by hand through the Bulk API needs the term created in its subscription's context — the #ContextOid initialization — which is exactly the machinery api/watch exists to spare you.