Files, email and people
Store files in buckets, send email, look people up and read your own permissions.
Besides the collections, the interface offers four more things: buckets for files, sending email, the directory of people and information about the signed-in person. The same rules apply to all of them as to data: session cookie, Content-Type: application/json for a JSON body, the same shape of error answer (Reading and writing data).
Enter in tool.json under uses what your tool needs of these: the bucket under buckets, mail.send and people.read under capabilities.
Files in a bucket
A bucket holds files. It stands next to the collections, never inside one. The agent creates it with ensure_bucket. As with data, permissions belong to a role, with the scopes none, own and all for reading and writing. own means the files the person uploaded themselves.
Files are kept per data space, like records: the bucket is the same in both rooms, its contents are not. In the practice room a tool only sees the files uploaded there, see Production and practice room.
| Call | What it does |
|---|---|
POST /api/buckets/<bucket>/files | uploads a file |
POST /api/buckets/<bucket>/files/query | lists files: {"limit": 50} gives {files, total, hasMore} |
GET /api/buckets/<bucket>/files/<id> | returns the file, always as a download |
DELETE /api/buckets/<bucket>/files/<id> | deletes the file. The call carries Content-Type: application/json |
Uploading a file
The bytes go in the body, the name in the X-File-Name header, percent-encoded. The instance does not accept multipart.
fetch("/api/buckets/belege/files", {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": file.type,
"X-File-Name": encodeURIComponent(file.name)
},
body: file // the File object from an <input type="file">
});
The answer is 201 with id, name, mediaType, bytes and checksum.
Limits
- The default is 25 MB per file and 1 GB per bucket. The quota counts per data space.
- The instance accepts only certain file types. The default: PDF, PNG, JPEG, GIF, WebP, text, CSV, ZIP, JSON, Word (
.docx) and Excel (.xlsx). - The instance checks the declared media type against the first bytes. It refuses a file that is called
.pngand is not one. - Every download comes as an attachment. So a stored image cannot be shown with
<img src>. - A bucket cannot be deleted, its files can.
Sending email
POST /api/mail sends a message. The person needs the capability mail.send through one of their roles.
{
"to": ["vera@example.com"],
"subject": "A new task for you",
"text": "You have a new task: check the offer.",
"replyTo": "reception@example.com"
}
- Required are at least one recipient, a subject and a body:
text,htmlor both.ccandbccare lists liketo. - The subject is one line of at most 200 characters.
- The sender is fixed per instance. A tool does not choose it. You can set
replyTo. - The default is at most 50 recipients per message and 200 messages per hour for the whole instance.
- Sending happens at once: 202 with
{"sent": true}means the message went out. On an error nothing went out. - The instance records every message in the audit log.
Looking people up
Do not let anyone type a name. Search the directory and store the id in a field of type person. The person needs the capability people.read. It is not part of admin rights either.
{"term": "ver", "limit": 50}
POST /api/people/query answers:
{"people": [{"id": "…", "name": "Vera Example", "email": "vera@example.com"}],
"total": 1, "hasMore": false}
GET /api/people/<id> turns a stored id back into a name. The directory holds everyone who has signed in at least once and is not disabled.
Who is signed in
GET /api/me names the signed-in person and their effective permissions:
{
"userId": "4b40b106-…",
"name": "Alex Admin",
"admin": true,
"roles": ["admin", "demo"],
"collections": [{"collection": "aufgaben", "read": "all", "write": "all"}],
"buckets": [{"bucket": "task_files", "read": "all", "write": "all"}],
"capabilities": ["people.read", "mail.send"],
"tools": ["tasklist"],
"contexts": []
}
Use the answer for “my tasks” (created_by equal to userId) and to hide buttons the person may not use. Hiding is a convenience: the instance checks every permission itself on every request.