Project Roles (api/ProjectRoles)
Reports which members hold which roles on which projects, from either direction — grouped by project, or grouped by member.
It is read-only by design. There is no create, update or delete here. Role assignments are changed through the Bulk API, which is the only API endpoint intended for that, and are governed by Agility's rights and privileges.
It Describes Itself
Unusually for Agility, this endpoint publishes a machine-readable specification of itself:
GET ~/api/ProjectRoles
returns a complete RAML 1.0 document as text/plain — type definitions, both resources,
their query parameters, response schemas and worked examples. Roughly 14 KB.
No authentication is required for the specification, which makes it usable for client
generation and exploration without a token. It returns
200 text/plain unauthenticated, while the two data resources below return 401.
Nothing else in the API publishes a machine-readable contract of itself. The API surface as a whole has no OpenAPI or RAML description — the only other machine-readable artifacts this site publishes are the ANTLR query grammars.
Do not generalise the pattern: api/ProjectRoles describes api/ProjectRoles and nothing else.
Resources
Both are GET and both require authentication.
Grouped by Project
GET ~/api/ProjectRoles/ByProject?where=Name='New Project'&membersWhere=Nickname='JDoe'
| Parameter | Description |
|---|---|
where | Filters the projects returned |
membersWhere | Filters the members within each project |
page | Pages the projects, and the members within each project — see Paging |
sort | Orders the projects — see Sort |
Returns { total, assets: ProjectMemberRoles[] }, where each entry pairs a project with the
members holding roles on it.
Grouped by Member
GET ~/api/ProjectRoles/ByMember?where=Nickname='JDoe'&projectsWhere=Name='New Project'
| Parameter | Description |
|---|---|
where | Filters the members returned |
projectsWhere | Filters the projects within each member |
page | Pages the members, and the projects within each member — see Paging |
sort | Orders the members — see Sort |
Returns { total, assets: MemberProjectRoles[] } — the same relationships from the other side.
Note the symmetry in the parameter naming: where always filters the thing you grouped by, and
the other parameter filters what is nested inside it.
Give at least one of the two filters. With neither, a resource returns no data: it answers
200 text/plain with its own section of the specification.
Paging
page takes two pages in one value, separated by a semicolon:
page=outerSize,outerStart;innerSize,innerStart
- The outer page applies to the list you grouped by: projects on
ByProject, members onByMember. - The inner page applies to the nested list inside each group, separately for each
group.
page=10,0;5,0returns up to 10 projects, each listing its first 5 members. The inner list is in ID order. - A size without a start means start
0, sopage=10ispage=10,0.
GET ~/api/ProjectRoles/ByProject?where=AssetState='64'&page=10,0;5,0
GET ~/api/ProjectRoles/ByProject?where=AssetState='64'&page=10,10;5,0
Without page, the outer list is not paged: every matching project (or member) comes
back in one response. The inner list is still capped at 50 per group, so a project with
more than 50 members is silently cut short unless you page its members yourself.
A page value that can't be parsed is not rejected. The segment falls back to 50,0, so a typo
gives you a different page, not a 400.
total Counts This Response, Not the Matches
total is the number of groups in this response. It is not the number of projects or members
that match where, and it can't tell you whether more pages remain:
ByProjectleaves out any project with no matching member roles.ByMemberleaves out any member with no matching project roles whenprojectsWhereis given.
So a page can hold fewer groups than its size while more remain. To know how many pages to
request, count the matches through rest-1 with the same where and an explicit
needTotal=true, which returns the total even for a one-row page:
GET ~/rest-1.v1/Data/Scope?where=AssetState='64'&page=1,0&needTotal=true
Use Data/Member for ByMember. Send needTotal=true every time; its default varies by instance
(see paging totals).
Sort
sort orders the list you grouped by: projects on ByProject, members on ByMember. It takes
one or more attribute names of that type, separated by commas, each optionally prefixed with -
for descending:
GET ~/api/ProjectRoles/ByProject?where=AssetState='64'&sort=-Name,+ID&page=10,0
- The default is
+ID. - The nested list is not affected: members within a project, and projects within a member, are always in ID order.
- An attribute name the server doesn't recognize is ignored without an error, and you get the default order. If your order looks like ID order, check the attribute name.
Response Shape
{
"total": 2,
"assets": [
{
"project": { "oidToken": "Scope:1003", "name": "New Project" },
"memberRoles": [
{
"isOwner": true,
"member": {
"oidToken": "Member:20",
"name": "Administrator",
"email": "admin@v1.com",
"defaultRole": { "oidToken": "Role:1", "name": "System Admin" }
},
"role": { "oidToken": "Role:1", "name": "System Admin" }
}
]
}
]
}
defaultRole and role are different things, and the difference mattersBoth appear in every response and they answer different questions.
member.defaultRoleis what the UI presents as Admin Privileges. It determines the member's global privileges, and it is the role they will act as by default when they are given access to a new Scope.roleis the role that member actually holds on this specific project.
They frequently differ, and neither implies the other. A member whose defaultRole is
Team Member can hold Project Lead on one project; a member whose defaultRole is
System Admin carries those global privileges regardless of what any individual project says.
If you are answering "what can this person do here?", read role. If you are answering "what
can this person do generally, and what will they get on their next project?", read
defaultRole.
isOwner flags the project owner, distinct from any role assignment.
Related
- Bulk API — the supported way to change role assignments
- Meta API —
Member,RoleandScopeschema - Query grammar — the filter syntax
whereaccepts