Skip to content

Users

View .md

A user is one of your people. Proof gives each user its own id, usr_…, and keeps your id for them beside it as external_id. Every other endpoint, event and seal names users by Proof id. Proof has no accounts and no sign-in: you create a user with a name, and from then on Proof credits what that user writes in the editor to that name. See Users for how the two ids, names, pictures and deletion work.

Attribute Type Description
id string Proof’s id for this user, usr_ and 8 characters. It never changes.
external_id string Your id for this user, 1 to 128 characters, unique on your platform in each mode.
name string The name Proof shows on their writing, comments, cursors and seals. Up to 48 characters.
avatar_url string or null Proof’s copy of their picture, or null for initials.
detail string or null A second line shown under their name where people pick someone to mention, such as an email address or a team.
created_at timestamp When you first created the user.
{
"id": "usr_5Kq2Lm8R",
"external_id": "u_42",
"name": "Ada Lovelace",
"avatar_url": "https://api.proof.exalto.ai/v1/avatars/av_9Rk3Tq",
"detail": "ada@acme.com",
"created_at": "2026-10-12T09:14:03Z"
}

PUT /v1/users/external/{external_id}

Creates a user for your id if there isn’t one, and replaces their name, picture and detail if there is. Call it when someone signs up, and again whenever their profile changes in your product. Keep the id it returns beside your user.

A new name shows everywhere at once, in every document and open editor, because documents name people by Proof id. Seals already made keep the name they were sealed with.

Parameter Type Description
external_id string, path, required Your id for this user. URL-encode it.
name string, required Up to 48 characters, without control or invisible characters.
avatar_url string An https URL of a PNG, JPEG or WebP picture of at most 1 MB, on a public address. Proof fetches it once and keeps its own copy; send the same URL again and it isn’t fetched again. null removes the picture. Leave it out to keep the current one.
detail string Up to 128 characters. null removes it. Leave it out to keep the current one.
Terminal window
curl https://api.proof.exalto.ai/v1/users/external/u_42 \
-X PUT \
-H "Authorization: Bearer $PROOF_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Ada Lovelace",
"avatar_url": "https://acme.com/avatars/42.png",
"detail": "ada@acme.com"
}'

Returns the user: 201 when it was created, 200 when it was updated.

{
"id": "usr_5Kq2Lm8R",
"external_id": "u_42",
"name": "Ada Lovelace",
"avatar_url": "https://api.proof.exalto.ai/v1/avatars/av_9Rk3Tq",
"detail": "ada@acme.com",
"created_at": "2026-10-12T09:14:03Z"
}
Error When
400 invalid_parameter on name The name is empty, longer than 48 characters, or has control or invisible characters.
400 invalid_parameter on external_id Empty, or longer than 128 characters.
400 avatar_unreadable Proof couldn’t fetch the picture, or it isn’t a PNG, JPEG or WebP of at most 1 MB.

GET /v1/users/{id}

Parameter Type Description
id string, path, required The user’s Proof id.
Terminal window
curl https://api.proof.exalto.ai/v1/users/usr_5Kq2Lm8R \
-H "Authorization: Bearer $PROOF_SECRET_KEY"

Returns the user, or 404 user_not_found.

GET /v1/users/external/{external_id}

For when you have only your own id, for example before you’ve stored the Proof id.

Parameter Type Description
external_id string, path, required Your id for this user. URL-encode it.
Terminal window
curl https://api.proof.exalto.ai/v1/users/external/u_42 \
-H "Authorization: Bearer $PROOF_SECRET_KEY"

Returns the user, or 404 user_not_found.

PATCH /v1/users/{id}

Changes any of a user’s fields by Proof id, including external_id: use it when your ids change, in a migration or when someone switches login method. Documents, seals and agents follow the Proof id, so nothing else moves.

Parameter Type Description
id string, path, required The user’s Proof id.
external_id string A new id of yours for this user. It must not belong to another user.
name string As in Create or update a user.
avatar_url string or null As above.
detail string or null As above.
Terminal window
curl https://api.proof.exalto.ai/v1/users/usr_5Kq2Lm8R \
-X PATCH \
-H "Authorization: Bearer $PROOF_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"external_id": "2f6c1e0a-7b1d-4c55-9e0f-3a8d2b6c9e41"}'

Returns the user.

Error When
409 external_id_taken Another user already has that external_id. Merge the two first if they’re the same person.
404 user_not_found No user with that id.

DELETE /v1/users/{id}

Removes the user from Proof. Call it when someone deletes their account in your product. Their external_id is free again afterwards; using it again creates a new person.

  • Documents they wrote in keep the last name they had, without their picture, so the record of who wrote what stays readable.
  • Documents they owned pass to their other members: those with the highest role become owners. A document with no other member passes to someone else who wrote in it, if anyone did, and is otherwise deleted, with its seals. One in the trash with no owner left is deleted.
  • Their agents are revoked, and their open editors close.
  • Their security keys and check-in history are deleted.
Parameter Type Description
id string, path, required The user’s Proof id.
Terminal window
curl https://api.proof.exalto.ai/v1/users/usr_5Kq2Lm8R \
-X DELETE \
-H "Authorization: Bearer $PROOF_SECRET_KEY"
{
"id": "usr_5Kq2Lm8R",
"deleted": true
}

POST /v1/users/{id}/merge

Moves everything from one user to another, then deletes the first. Use it when someone who started without an account signs up or signs in, so their work comes with them. See Anonymous users.

What moves:

  • their documents and memberships (where both users were members, the higher role is kept), and documents in their own trash
  • the credit for everything they and their agents wrote, typed, shaped or accepted, in every document
  • their security keys (after into’s own), their check-ins, their presence signals, and their check-in interval unless into already has one
  • their agents. An agent for a client into already has an agent for joins that one, keeping the higher role in each document and its tokens, so it needn’t be approved again.

Open editors of the user merged from lose their sessions: start new ones as into.

Parameter Type Description
id string, path, required The user to merge from. It’s deleted afterwards.
into string, required The Proof id of the user to merge into. It must exist.
Terminal window
curl https://api.proof.exalto.ai/v1/users/usr_2Hd7Np4Q/merge \
-H "Authorization: Bearer $PROOF_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"into": "usr_5Kq2Lm8R"}'

Returns the user merged into.

{
"id": "usr_5Kq2Lm8R",
"external_id": "u_42",
"name": "Ada Lovelace",
"avatar_url": null,
"detail": "ada@acme.com",
"created_at": "2026-10-30T18:20:00Z"
}
Error When
400 invalid_parameter on into into is the same user.
404 user_not_found Either user doesn’t exist.

GET /v1/users/{id}/documents

The documents a user is a member of, most recently edited or shared with them first, leaving out those in the trash. Use it to build your document list; keep your own folders and pins beside it, keyed by document id.

Parameter Type Description
id string, path, required The user’s Proof id.
ids string Comma-separated document ids: only those of them the user may open now, as a member or by link access. For titles and access of documents you keep elsewhere, such as in a notification list.
trashed boolean true lists what’s in their trash instead, most recently trashed first: documents an owner trashed for everyone, where they’re an owner, and documents they put in their own. Default false.
limit integer 1 to 100. Default 50.
after string The next cursor from the previous page.
Terminal window
curl "https://api.proof.exalto.ai/v1/users/usr_5Kq2Lm8R/documents?limit=2" \
-H "Authorization: Bearer $PROOF_SECRET_KEY"

Each item is a document with two more fields: role, this user’s role in it (the higher of their member role and the link’s), and added_at, when they became a member, or null for one they reach by link. With trashed=true, each has instead everyone, true when it’s in the trash for everyone and false when only in theirs, and in_trash_since.

{
"data": [
{
"id": "doc_8Hq2Lm4R",
"name": "On the Analytical Engine",
"title": "On the Analytical Engine",
"owners": ["usr_5Kq2Lm8R"],
"link_access": "restricted",
"created_at": "2026-10-13T21:12:40Z",
"edited_at": "2026-10-13T23:30:52Z",
"trashed_at": null,
"role": "owner",
"added_at": "2026-10-13T21:12:40Z"
},
{
"id": "doc_3Wp7Zc1V",
"name": null,
"title": "Notes for Thursday",
"owners": ["usr_9Tb3Wc1X"],
"link_access": "suggest",
"created_at": "2026-10-11T15:02:11Z",
"edited_at": "2026-10-12T08:47:30Z",
"trashed_at": null,
"role": "suggester",
"added_at": "2026-10-11T15:40:02Z"
}
],
"next": "c_2Fh8Kq"
}

DELETE /v1/users/{id}/trash

DELETE /v1/users/{id}/trash/{document_id}

Deletes for good everything in a user’s trash, or one document there. A document in the trash for everyone, where they’re an owner, is deleted for everyone; one in their own trash they leave, as a member, and it stays for the others.

Parameter Type Description
id string, path, required The user’s Proof id.
document_id string, path One document in their trash.
Terminal window
curl https://api.proof.exalto.ai/v1/users/usr_5Kq2Lm8R/trash \
-X DELETE \
-H "Authorization: Bearer $PROOF_SECRET_KEY"
{ "user": "usr_5Kq2Lm8R", "deleted": 3 }

For one document, { "user": …, "document": …, "deleted": true }, or 404 document_not_found when it isn’t in their trash.

DELETE /v1/users/{id}/sessions

Ends a user’s editor and presence sessions, all of them or one group’s, as when they sign out. Described with the other session endpoints: see End a user’s sessions.

GET /v1/users/{id}/agents

The agents a user has connected, newest first. This endpoint is described with the other agent endpoints: see List a user’s agents.

GET /v1/users/{id}/checkins

How often a user is asked to check in with a security key while they write, and how many keys they have. See Presence and check-ins.

Parameter Type Description
id string, path, required The user’s Proof id.
Terminal window
curl https://api.proof.exalto.ai/v1/users/usr_5Kq2Lm8R/checkins \
-H "Authorization: Bearer $PROOF_SECRET_KEY"
{
"user": "usr_5Kq2Lm8R",
"every_minutes": 10,
"security_keys": 2
}
Attribute Type Description
user string The user’s Proof id.
every_minutes integer or null 1, 5, 10 or 30: about how often they’re asked while writing. null when check-ins are off.
security_keys integer How many security keys they’ve added. Keys are added only in presence settings, on Proof’s own domain.

PUT /v1/users/{id}/checkins

Turns check-ins on or off, or changes how often they’re asked. People can also change this themselves in the presence settings window, where they add their keys.

Parameter Type Description
id string, path, required The user’s Proof id.
every_minutes integer or null, required 1, 5, 10 or 30, or null to turn check-ins off.
Terminal window
curl https://api.proof.exalto.ai/v1/users/usr_5Kq2Lm8R/checkins \
-X PUT \
-H "Authorization: Bearer $PROOF_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"every_minutes": 5}'
{
"user": "usr_5Kq2Lm8R",
"every_minutes": 5,
"security_keys": 2
}
Error When
400 invalid_parameter on every_minutes Not one of 1, 5, 10, 30 or null.
409 no_security_keys The user has no security keys yet. Open presence settings for them to add one.