Skip to main content

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.

This is the only self-describing Agility endpoint

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'
ParameterDescription
whereFilters the projects returned
membersWhereFilters the members within each project
pagePages the projects, and the members within each project — see Paging
sortOrders 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'
ParameterDescription
whereFilters the members returned
projectsWhereFilters the projects within each member
pagePages the members, and the projects within each member — see Paging
sortOrders 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 on ByMember.
  • The inner page applies to the nested list inside each group, separately for each group. page=10,0;5,0 returns 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, so page=10 is page=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
Always send an outer page

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:

  • ByProject leaves out any project with no matching member roles.
  • ByMember leaves out any member with no matching project roles when projectsWhere is 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" }
}
]
}
]
}
tip
defaultRole and role are different things, and the difference matters

Both appear in every response and they answer different questions.

  • member.defaultRole is 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.
  • role is 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.

  • Bulk API — the supported way to change role assignments
  • Meta API — Member, Role and Scope schema
  • Query grammar — the filter syntax where accepts