HTTP API: users
The 4 operations tagged users, each with its parameters, its body and what it answers.
List the accounts on this instance
GET /v1/users
Who is on this instance, oldest first.
Paged like every other listing here (SR#2384). It used to take a ceiling of 200 rows
from the domain, supply no limit of its own, and answer with a literal
has_more: false — so past two hundred accounts it dropped rows and stated there were no
more, with a null total that could not contradict it. The docstring said has_more was
always false for the same reason a task's links are, and that reason does not survive a
ceiling: a task's links are bounded by what somebody typed, where this was bounded by a
number we chose.
answers_to names a person and returns the agents answerable to them (SR#2387),
directly or through another. It exists because paging this listing would otherwise break the
one thing that reads it whole: subroutine user deactivate says "this also stops N
agent(s)" before it acts, and a confirmation that under-reports is worse than the truncation
this route was fixed for. A caller wanting one account by name wants
GET /v1/users/{username} (SR#2386) rather than this listing and a filter in their own
code.
total is opt-in, which is §8.4's rule; the old envelope answered null and meant
nothing by it.
Parameters
answers_to(stringornull, in query): Only the agents answerable to this person, directly or through another.limit(integerornull, in query): How many to return. At least 1; capped at the instance's max_page_size.cursor(stringornull, in query): Continue after a previous page.include_total(boolean, in query): Count the whole result.format(stringornull, in query): 'full' (default), 'compact' for one aligned line per item, or 'ids' for the addresses alone. Compact is roughly a twentieth the size of full.fields(stringornull, in query): Comma-separated field names to return instead of the whole item, e.g. 'ref,title,due_at'. GET /v1/meta lists what each entity has. Cannot be combined with 'format'.
Responses
200:Collection_User_. Successful Response422:HTTPValidationError. Validation Error
Create an account
POST /v1/users
Add a person, or a machine identity, to this instance.
Needs instance:user_create. The new account belongs to no workspace yet — joining it to
one is a separate act with a separate permission, because deciding that somebody exists and
deciding where they may work are different decisions and often different people.
Request body: Create as application/json, required.
Responses
201:User. Successful Response422:HTTPValidationError. Validation Error
Read one account
GET /v1/users/{username}
Read the account with this name — SR#2386.
The API was behind its own domain here. domain.users.by_username has always existed
and both POST and PATCH resolve through it; nothing published a way to read one
account, so a caller wanting si fetched the whole directory and filtered it themselves.
That is a client re-implementing a lookup the server owns, and it is why paging the listing
could not be done on its own (SR#2384).
Readable by anyone authenticated, for the same reason the listing is: an identifier is unique and public where content is neither, and this view carries no email address and no content at all.
Case-insensitive, because by_username resolves through the normalised column — Simon
and simon being two accounts would be a trap rather than a feature.
Parameters
username(string, in path, required)
Responses
200:User. Successful Response422:HTTPValidationError. Validation Error
Mark somebody as having left, hand an agent over, or say where you are
PATCH /v1/users/{username}
Mark somebody as having left or brought back, or hand an agent to somebody else.
Both in one call, and the order is deliberate: handing the agents over happens before the deactivation, so somebody clearing up after a leaver in a single request keeps what they meant to keep.
Needs instance:user_create — the same grant as making an account, because deciding
somebody works here and deciding they no longer do are the same decision twice.
Except timezone, which needs no permission and is refused for anybody but yourself.
The check is are you this person, not something anybody can be granted: §6.5's user level
records where somebody keeps their diary, and a permission to write it would be a
permission to be wrong on their behalf.
Deactivating stops every agent answerable to that person, at their next call, wherever
they are running. Ask for the list first with GET /v1/users?answers_to=<username>: the
CLI names them before it does it, and a caller here should too. That used to say to read
GET /v1/users and pick the rows out by responsible_user_id — which was a whole
directory fetched to answer one question, and it stopped being possible the moment that
listing was paged (SR#2384, SR#2387). It also only ever found the agents answerable
directly; the filter walks the chain, which is what "answerable to that person" means
one sentence above.
The last person who can administer the instance is refused, because an instance nobody can administer cannot be repaired from inside and would have stopped every agent on it.
Parameters
username(string, in path, required)
Request body: Update as application/json, required.
Responses
200:User. Successful Response422:HTTPValidationError. Validation Error