Sharing
Share a Query with individual Users and Teams by granting each principal an access level on the Query.
A share binds a principal (a User or a Team) to a Query at a numeric
accessLevel. Listing and reading shares need only an authenticated caller;
the read_access scope already limits which Queries the caller can resolve.
Creating, updating, or removing a share requires the query:share permission.
A principalId is either a username (for a User) or a team id in the form
team:{slug} (for a Team).
GET /api/queries/{id}/shares
List every share on a Query.
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query id (UUID) or natural id |
Response:
A HAL collection (inf:query-all-shares embedding inf:query-share),
serialized as a plain array of share rows. Each row is built from a SQL join on
the principal table, so it carries the principal's resolved display identity
rather than a bare share record: for a User the row includes username,
displayName, email, and avatar fields; for a Team it includes the Team
name, icon, and color. A share appears only once its principal exists, and
only when accessLevel is greater than 0.
[
{
"queryId": "00000000-0000-4000-8000-000000000001",
"principalId": "annie.larson",
"accessLevel": 2,
"id": "annie.larson",
"teamId": null,
"name": "Annie Larson",
"materialIcon": null,
"icon": null,
"color": null,
"username": "annie.larson",
"displayName": "Annie Larson",
"email": "annie.larson@example.com",
"avatarUpdatedAt": null,
"type": "User",
"avatarColor": {
"background": "#81C784",
"text": "#1B5E20"
},
"colorIndex": 4,
"initials": "AL"
}
]
This is not a paged envelope and does not use the inf:share shape; it is the
identity-resolved list described above.
GET /api/queries/{id}/shares/{principalId}
Retrieve a single principal's share on a Query.
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query id (UUID) or natural id |
principalId | string | Username, or a team id (team:{slug}) |
Response:
The bare QueryShare row (queryId, principalId, accessLevel, plus the
standard tenant, createdAt, and updatedAt). This is a different shape from
the list route: it does not resolve the principal's display identity. Answers
404 when the principal has no share on the Query.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/queries/admin%3Asales-analysis-query/shares/annie.larson"
}
},
"id": "00000000-0000-4000-8000-000000000001",
"tenant": "acme",
"queryId": "00000000-0000-4000-8000-000000000002",
"principalId": "annie.larson",
"accessLevel": 2,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z"
}
{
"statusCode": 404,
"error": "Not Found",
"message": "Not Found"
}
PUT /api/queries/{id}/shares/{principalId}
Create or update a principal's share on a Query. The handler upserts the share, so a first call creates it and a later call updates it.
Authentication: Required
Permission: query:share
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query id (UUID) or natural id |
principalId | string | Username, or a team id (team:{slug}) |
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
accessLevel | integer | Yes | Access level; must be an integer of at least 1 |
The route allows unknown payload keys, so extra fields are tolerated rather than stripped.
Example Request:
{
"accessLevel": 2
}
Response:
Responds 200 with the upserted share row. Both create and update return 200;
the upsert handler returns the instance and never calls .created(), so there
is no 201. Creating or updating a share records a queryShared activity entry
for audit logging.
{
"accessLevel": 2
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/queries/admin%3Asales-analysis-query/shares/annie.larson"
}
},
"tenant": "acme",
"id": "00000000-0000-4000-8000-000000000001",
"queryId": "00000000-0000-4000-8000-000000000002",
"principalId": "annie.larson",
"accessLevel": 2,
"updatedAt": "2026-01-15T16:20:00.000Z",
"createdAt": "2026-01-15T16:20:00.000Z",
"_altid": null
}
To revoke a principal's access, use DELETE. Do not set accessLevel: 0; the
payload requires an integer of at least 1.
DELETE /api/queries/{id}/shares/{principalId}
Remove a principal's share from a Query.
Authentication: Required
Permission: query:share
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query id (UUID) or natural id |
principalId | string | Username, or a team id (team:{slug}) |
Response:
Responds 200 with an empty body (Informer convention), not 204. Deleting a
share revokes all access that share granted to the principal; to lower or raise
access instead, use PUT.