De REST API
Alles wat de Antimatter-apps doen verloopt via dezelfde HTTP API, dus je scripts kunnen hetzelfde. Deze pagina legt uit hoe je je identificeert, de bronnen die je het meest zult gebruiken, hoe antwoorden en fouten eruitzien en hoe je live gebeurtenissen volgt via de WebSocket.
Basis
- Basis-URL:
https://chat.example.com/api/v4. Alle endpoints hieronder zijn relatief ten opzichte daarvan. - Formaat: JSON in en uit, behalve bij het uploaden van bestanden (multipart). Stuur
Content-Type: application/json. - ID’s: elk object heeft een
idvan 26 tekens. Tijden zijn milliseconden sinds de Unix-epoch (create_at,update_at,delete_at; 0 betekent “niet verwijderd”). - Gemeenschappen zijn teams: de API noemt ze
teams, met eenteam_id. - jezelf: overal waar een pad een
user_idverwacht, betekentmede aangemelde gebruiker, zoals inGET /users/me.
De volledige lijst met eindpunten staat in de code van de server: de routes zijn gedefinieerd in server/channels/api4/*.go en de types in server/public/model. De OpenAPI-beschrijving in de map api/v4/source van het repository dekt de eindpunten die zijn overgenomen van Mattermost, en enkele toevoegingen van Antimatter: het verplaatsen van draadjes, modelverbindingen en berichtacties. De overige eindpunten zijn alleen in de code te vinden.
Authenticatie
Elk verzoek, behalve het aanmelden en enkele openbare endpoints, vereist een token in de Authorization-header:
curl -H "Authorization: Bearer $TOKEN" https://chat.example.com/api/v4/users/me
Er worden drie soorten tokens daar geaccepteerd: persoonlijke toegangstokens, sessietokens en OAuth-toegangstokens. Ook Authorization: Token … wordt geaccepteerd. Tokens in de querystring (?access_token=) worden alleen geaccepteerd voor OAuth-toegangstokens.
Persoonlijke toegangstokens (aanbevolen voor scripts)
Een persoonlijke toegangstoken handelt in jouw naam, verloopt niet tenzij je een vervaldatum geeft en kan op elk moment worden ingetrokken. Persoonlijke toegangstokens zijn standaard uitgeschakeld:
- Een systeembeheerder schakelt Persoonlijke toegangstokens inschakelen in via Systeemconsole › Integraties › Integratiebeheer (
ServiceSettings.EnableUserAccessTokens,AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS). - Voor elke persoon die tokens mag aanmaken, opent een systeembeheerder Systeemconsole › Gebruikersbeheer › Gebruikers, kiest Rollen beheren in het menu van de persoon en vinkt Sta dit account toe om persoonlijke toegangstokens te genereren aan. Systeembeheerders kunnen ze altijd aanmaken.
- De persoon opent de eigen avatar rechtsboven, daarna Profiel & instellingen › Beveiliging. Onder Persoonlijke toegangstokens beschrijft de persoon waar het token voor is en kiest Nieuw Token Aanmaken. Het token wordt slechts één keer getoond: kopieer het.
Met de API: POST /users/{user_id}/tokens met {"description": "backup script", "expires_at": 0} (expires_at in milliseconden; 0 voor geen). Het token-veld in de respons is het geheim; de id is wat je gebruikt om het te intrekken (POST /users/tokens/revoke met {"token_id": "…"}). Vanuit de opdrachtregel: amctl token generate <user> <description>.
Een systeembeheerder kan de levensduur van tokens beperken met Maximale levensduur persoonlijke toegangstokens (dagen) op dezelfde Systeemconsole-pagina.
Sessietokens
Inloggen met een wachtwoord geeft een sessietoken terug in de Token-responsheader, hetzelfde type sessie dat de apps gebruiken:
curl -i -X POST https://chat.example.com/api/v4/users/login \
-H 'Content-Type: application/json' \
-d '{"login_id": "maya", "password": "…"}'
Voeg "token": "123456" toe voor een account met meervoudige verificatie. Sessies verlopen zoals de sessie-instellingen van de server voorschrijven, en het inlogpunt is rate-limited (5 verzoeken per seconde). POST /users/logout beëindigt de sessie.
X-CSRF-Token-header versturen; een token in de Authorization-header vereist geen CSRF-header.OAuth 2.0-apps
Om mensen toe te staan in te loggen op uw toepassing met hun Antimatter-account, registreert u een OAuth 2.0-app. Antimatter is dan de OAuth-provider:
- Aanzetten van OAuth 2.0 Service Provider moet ingeschakeld zijn (Systeemconsole › Integraties › Integratiebeheer,
ServiceSettings.EnableOAuthServiceProvider, standaard ingeschakeld). - Iemand met het recht om OAuth-apps te beheren (standaard systeembeheerders) opent de eigen avatar, vervolgens Integraties › OAuth 2.0-apps, en voegt de app toe met de callback-URL’s. Ze krijgen een client ID en een client secret.
- Uw applicatie stuurt mensen door naar
https://chat.example.com/oauth/authorizemetresponse_type=code,client_id,redirect_urienstate. PKCE metcode_challenge_method=S256wordt ondersteund. - Daarna wisselt het de code in bij
POST https://chat.example.com/oauth/access_token(grant_type=authorization_code, en daarnarefresh_tokenom te vernieuwen) en roept het de API aan metAuthorization: Bearer <access token>.
Gebruikers zien de apps waaraan ze toegang hebben gegeven in Profiel & instellingen › Beveiliging › Apps waaraan je toegang hebt gegeven.
Belangrijkste bronnen
| Wat | Endpoints |
|---|---|
| U en andere mensen | GET /users/me, GET /users/{user_id}, GET /users/username/{username}, POST /users/ids (een lijst met IDs), POST /users/search, GET /users?in_team=…&in_channel=… |
| Gemeenschappen | GET /users/me/teams, GET /teams/{team_id}, GET /teams/name/{name}, PUT /teams/{team_id}/patch, GET /teams/{team_id}/members, POST /teams/{team_id}/members |
| Kanalen | GET /users/me/teams/{team_id}/channels, GET /teams/name/{team}/channels/name/{channel}, POST /channels, POST /channels/direct (twee gebruikers-ID's), POST /channels/group, POST /channels/{channel_id}/members |
| Berichten | POST /posts, GET /posts/{post_id}, PUT /posts/{post_id}/patch, DELETE /posts/{post_id}, GET /channels/{channel_id}/posts, GET /posts/{post_id}/thread, POST /teams/{team_id}/posts/search |
| Reacties | POST /reactions met {"user_id", "post_id", "emoji_name"}, DELETE /users/{user_id}/posts/{post_id}/reactions/{emoji_name} |
| Bestanden | POST /files (multipart: channel_id en files), en voeg de teruggegeven IDs toe aan file_ids van het bericht; GET /files/{file_id} |
| Voorkeuren | GET /users/me/preferences, PUT /users/me/preferences |
| Integraties | /hooks/incoming, /hooks/outgoing, /commands, /bots, /oauth/apps (zie de volgende pagina's) |
| Server | GET /system/ping (gezondheid, geen token vereist), GET /config/client?format=old (de instellingen die clients zien) |
Een bericht plaatsen
curl -X POST https://chat.example.com/api/v4/posts \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"channel_id": "'$CHANNEL_ID'", "message": "Backup finished: **42 GB** in 3 min"}'
Berichten zijn Markdown. Voeg "root_id" (het eerste bericht van een draadje) toe om in een draadje te antwoorden, "file_ids" voor bestanden en "props" voor bijlagen en andere extra's (zie Bijlagen).
Het ID van een kanaal vinden
curl -H "Authorization: Bearer $TOKEN" \
https://chat.example.com/api/v4/teams/name/lumen-labs/channels/name/ops-alerts
De namen zijn die in de link van het kanaal: /lumen-labs/channels/ops-alerts.
Paginering
Lijst-endpoints accepteren page (vanaf 0) en per_page (standaard 60, maximaal 200). Blijf de volgende pagina opvragen totdat een pagina korter is dan per_page.
De berichten van een kanaal (GET /channels/{channel_id}/posts) accepteren ook since (een tijdstip: alles wat sindsdien is gewijzigd), of before en after (een bericht-ID). Ze worden teruggegeven als een lijst met berichten: {"order": [IDs, newest first], "posts": {ID: post}, "next_post_id", "prev_post_id"}.
Fouten
Fouten gebruiken de gebruikelijke HTTP-statuscodes (400 ongeldige invoer, 401 niet aangemeld, 403 niet toegestaan, 404 niet gevonden, 501 functie uitgeschakeld) en een JSON-lichaam:
{
"id": "api.context.permissions.app_error",
"message": "You do not have the appropriate permissions.",
"detailed_error": "",
"request_id": "jz8zm5nunpbt8f3gpqsz5dq6so",
"status_code": 403
}
Gebruik id in uw code: message wordt vertaald naar de taal van de gebruiker. detailed_error is leeg, tenzij de server in ontwikkelaarsmodus draait (ServiceSettings.EnableDeveloper). Vermeld request_id bij de beheerder van de server: deze staat in de logs.
Snelheidslimieten
Snelheidsbeperking is standaard uitgeschakeld. Wanneer een systeembeheerder deze inschakelt (Systeemconsole › Omgeving › Snelheidsbeperking), krijgt elke client standaard 10 verzoeken per seconde met pieken van 100, geteld op IP-adres of op gebruiker. Antwoorden bevatten X-RateLimit-Limit, X-RateLimit-Remaining en X-RateLimit-Reset; boven de limiet antwoordt de server met 429 en een Retry-After-header in seconden. Sommige eindpunten, zoals het aanmelden, hebben hun eigen limiet ongeacht de instelling.
Schrijf scripts die wachten en opnieuw proberen bij 429, en vermijd polling: gebruik in plaats daarvan de WebSocket.
De WebSocket-gebeurtenisstream
Maak een verbinding met wss://chat.example.com/api/v4/websocket. Authenticatie gebeurt via de Authorization: Bearer-header in het verzoek voor de verbinding, of door dit als eerste bericht te verzenden:
{"seq": 1, "action": "authentication_challenge", "data": {"token": "…"}}
De server stuurt een hello-gebeurtenis, gevolgd door een gebeurtenis voor alles waarvoor u bevoegdheid heeft:
{
"event": "posted",
"data": {"channel_id": "…", "channel_type": "O", "post": "{\"id\":\"…\",\"message\":\"Hello\",…}"},
"broadcast": {"channel_id": "…", "team_id": "", "user_id": "", "omit_users": null},
"seq": 4
}
Merk op dat data.post het bericht is als een JSON-tekenreeks. Veelvoorkomende gebeurtenissen: posted, post_edited, post_deleted, reaction_added, reaction_removed, typing, status_change, user_added, direct_added. Apps sturen hun eigen gebeurtenissen, genaamd custom_<app id>_<event>.
U kunt ook acties verzenden, elk met een toenemende seq: user_typing met {"channel_id", "parent_id"}, of get_statuses. Herstel de verbinding wanneer deze verbroken is, en haal wat u hebt gemist op met since (zie Paginering).
Antimatter voegt de volgende gebeurtenissen toe: community_attributes_updated, member_timeouts_updated, post_put_on_top, post_removed_from_top, server_categories_updated, channel_overrides_updated en category_overrides_updated.
Clientbibliotheken
- Ga:
model.Client4inserver/public/model(importgithub.com/mattermost/mattermost/server/public/model).model.NewAPIv4Client(url), daarnaclient.SetToken(token);model.NewWebSocketClient4(wsURL, token)volgt gebeurtenissen. De kopie van Antimatter voegt methoden toe voor de eigen eindpunten, zoalsUpdateMessageRequest,PutPostOnTopenExportChannel. - TypeScript: de
Client4-klasse van@mattermost/client, te vinden inwebapp/platform/client, met de bijbehorende types inwebapp/platform/types. De kopie in het repository van Antimatter bevat de eindpunten van Antimatter; het pakket dat Mattermost op npm publiceert, niet.
package main
import (
"context"
"log"
"github.com/mattermost/mattermost/server/public/model"
)
func main() {
client := model.NewAPIv4Client("https://chat.example.com")
client.SetToken("…")
post, _, err := client.CreatePost(context.Background(), &model.Post{
ChannelId: "…",
Message: "Hello from Go",
})
if err != nil {
log.Fatal(err)
}
log.Println("posted", post.Id)
}
Wat Antimatter aan de API toevoegt
Deze eindpunten en velden bestaan niet op een Mattermost-server. Ze vereisen allemaal een sessie.
| Eindpunt | Wat het doet |
|---|---|
GET /teams/{team_id}/user_attributes/fieldsPOST zelfde padPATCH, DELETE …/fields/{field_id} | Community-attributen: de profielvelden die beheerders van een community definiëren voor de leden (maximaal 20). Leden kunnen ze lezen; communitybeheerders maken ze aan en wijzigen ze. |
GET /teams/{team_id}/members/{user_id}/user_attributesPATCH zelfde padPOST /teams/{team_id}/user_attributes/values/search | De attribuutwaarden van een lid, in de vorm {field_id: value}. Leden stellen hun eigen waarden in (behalve de door beheerders beheerde); beheerders kunnen de waarden van iedereen instellen. De zoekopdracht accepteert {"user_ids": [...]} (maximaal 200). |
GET /teams/{team_id}/timeoutsPUT /teams/{team_id}/members/{user_id}/timeoutGET /teams/{team_id}/members/{user_id}/moderation | Time-outs: {"until": time, "reason": "…"} verhindert dat iemand tot die tijd (maximaal 28 dagen) berichten plaatst, reageert of bestanden uploadt in de community; "until": 0 heft de time-out op. Het moderatieoverzicht toont wanneer het lid is toegetreden en hoeveel het onlangs heeft gepost. |
GET /channels/{channel_id}/on_topPUT, DELETE /posts/{post_id}/on_top | Berichten die bovenaan een kanaal worden vastgemaakt (maximaal 10). {"duration": ms}, maximaal 30 dagen; 0 houdt het vast totdat het wordt verwijderd. Iedereen die het kanaal kan lezen, ziet ze in de lijst. Om een bericht bovenaan te zetten of te verwijderen, heb je het recht nodig om in het kanaal te posten en, in het kanaal van een community, moet je beheerder zijn van het kanaal of de community, of daar Berichten beheren (delete_others_posts) hebben. In een privé- of groepsbericht kunnen de leden dit doen. In gearchiveerde kanalen wordt dit geweigerd. |
POST /channels/{channel_id}/message_request | Werkt op uw eigen berichtverzoek: {"action": "accept"}, "dismiss" of "request" om een conversatie terug te plaatsen onder de verzoeken. Geeft uw kanaallidmaatschap terug. |
GET, PUT /channels/{channel_id}/overridesGET /channels/{channel_id}/overrides/effectiveGET, PUT /channels/{channel_id}/role_access | Wat een rol of persoon in een kanaal mag doen, en welke rollen een kanaal met rolbeperkingen kunnen zien. |
GET, PUT /teams/{team_id}/server_categoriesGET, PUT …/server_categories/overrides | De gedeelde categoriën van de community, en de overriden die gelden voor elk kanaal in een categorie. |
GET /groups/{group_id}/team_rolePUT …/team_role/permissions | De rechten die een communityrol verleent. |
POST /teams/{team_id}/autolinks/preview | Test de autolink-regels van de community op een tekst. |
POST /channels/{channel_id}/export?format=csv&since=&until= | Downloadt de berichten van een kanaal als CSV (maximaal 50.000), voor personen die het kanaal kunnen lezen. |
GET /posts/{post_id}/speech | De boodschap die als audio wordt voorgelezen wanneer tekst-naar-spraak is geconfigureerd. |
POST /posts/{post_id}/move_to_channel | Verplaatst een draadje naar een ander kanaal in dezelfde community: zie Een draadje verplaatsen. |
GET, POST /ai/connectionsGET, PATCH, DELETE /ai/connections/{connection_id}GET /ai/connections/usable | Modelverbindingen, de AI-aanbieders die de AI-functies en apps van de server gebruiken: zie Modelverbindingen. |
GET /channels/{channel_id}/message_actionsPOST /posts/{post_id}/message_actions/{hook_id}GET, POST /hooks/outgoing/{hook_id}/icon | Berichtacties: uitgaande webhooks die mensen uitvoeren vanuit het berichtmenu. Zie Berichtacties. |
Nieuwe velden
- Communities (
Team, enPUT /teams/{team_id}/patch):all_channels_membership(iedereen is lid van elk kanaal dat ze mogen zien),default_channel_id(waar nieuwe leden terechtkomen; leeg betekent Algemeen),kind(communityofworkplace: in een workplace kunnen kanaalbeheerders hun kanalen ook archiveren; nieuwe communities krijgen hetTeamSettings.DefaultCommunityKindvan de server, standaardcommunity),member_list_view(hoe de ledenlijst leden groepeert:choice, de standaard, laat elk lid kiezen;rolesofteamsis vast),hide_role_colors,require_team_badges,onboardingenautolinks(beide JSON-strings). - Het standaardkanaal van een nieuwe community is
general(Algemeen), niettown-square. De upgrade naar 0.9.0 hernoemt hettown-square-kanaal van elke community naargeneral, waarbij de ID behouden blijft, tenzij de community al eengeneral-kanaal heeft. De oude namen blijven werken:GET /teams/{team_id}/channels/name/town-square,GET /teams/name/{team}/channels/name/town-squareen hetchannel-veld van een inkomende webhook geven het standaardkanaal van de community terug als er geen kanaal met die naam bestaat. Gebruik in nieuwe codedefault_channel_idof de naamgeneral. - Kanaallinks:
#channel-namekoppelt een kanaal, net zoals~channel-name. Dechannel_mentions-eigenschap van het bericht toont de kanalen die op die manier zijn gekoppeld; een#wordzonder kanaalnaam blijft een hashtag. De webinterface en de mobiele app van Antimatter schrijven#name. - Gearchiveerde Kanalen kunnen nog steeds nieuwe leden toevoegen (
POST /channels/{channel_id}/members), die hun geschiedenis kunnen lezen. Niemand kan daar berichten plaatsen, reageren, vastmaken, een bericht bovenaan zetten, het kanaal hernoemen of de rollen van de leden wijzigen. - Inlineresponses: een bericht met
"props": {"reply_to": "<post id>"}citeert dat bericht uit hetzelfde kanaal. Voeg"reply_to_mention": falsetoe om de auteur niet te verwittigen. De server vultmetadata.reply_toin met een korte beschrijving van het geciteerde bericht. - Spoilers:
"props": {"spoiler": true}verbergt de tekst en bestanden van een bericht tot de lezer kiest om ze te bekijken. - Negeren en blokkeren zijn voorkeuren: categorie
user_block, vernoemd naar het ID van de andere persoon, met de waardeignoreofblock. Of een privébericht als verzoek wacht, staat innotify_props.dm_requestvan uw kanaallid (pending,acceptedofdismissed). - Berichtbijlagen kunnen
stagesen eenchartbevatten: zie Kaarten.
Een draadje verplaatsen
POST /posts/{post_id}/move_to_channel verplaatst een draadje, het eerste bericht en alle antwoorden, naar een ander kanaal in dezelfde community. post_id kan het eerste bericht zijn of een willekeurig antwoord.
curl -X POST https://chat.example.com/api/v4/posts/$POST_ID/move_to_channel \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"channel_id": "'$TARGET_CHANNEL_ID'", "flatten": false}'
channel_id(verplicht): het kanaal waarnaar het draadje wordt verplaatst.flatten(standaardfalse):truemaakt van de antwoorden gewone berichten in het doelkanaal in plaats van een draadje. Make it a channel in Fusion gebruikt dit.
De berichten behouden hun auteurs, tijdstippen, reacties en bestanden. Hun kopieën hebben de silent_notification-eigenschap, zodat ze niemand informeren. De oorspronkelijke berichten worden verwijderd. Het antwoord is het verplaatste eerste bericht, met zijn nieuwe ID.
Wie een draadje mag verplaatsen
- Je moet in staat zijn het draadje te lezen en in het doelkanaal te kunnen posten.
- De beheerders van het kanaal, de beheerders van de community, personen met Berichten beheren (
delete_others_posts) in het kanaal en systeembeheerders mogen elk draadje verplaatsen. - De auteur van het draadje mag het verplaatsen wanneer beide kanalen publiek zijn, of wanneer alle berichten in het draadje van hem/haar zijn. Anders is het antwoord
403met de IDapi.post.move_thread.private_needs_moderator.app_error. - Beide kanalen moeten in dezelfde community zitten (geen privé- of groepsberichten), van elkaar verschillen en niet gearchiveerd zijn. Systeem- en burn-on-read-berichten kunnen niet worden verplaatst.
- Een draadje met meer dan
WranglerSettings.MoveThreadMaxCountberichten (standaard 100; 0 voor geen limiet) wordt geweigerd.
De pointer en de notitie
De verplaatsing laat twee systeemmeldingen van het type system_wrangler achter: een pointer in het oude kanaal ("Een draadje met 13 berichten is verplaatst naar #target") en een notitie in het doelkanaal ("Dit draadje is verplaatst vanuit #source"), onder het verplaatste draadje of, met flatten, na de berichten. Naast de berichttekst laten de props een client de kanaalnaam als link weergeven:
- De pointer:
MovedThreadPermalink,NumMessages,MovedThreadChannelId,MovedThreadTeamName,MovedThreadPostIden, voor een publiek doelkanaal,MovedThreadChannelNameenMovedThreadChannelDisplayName. - De notitie:
MovedFromChannelId,MovedFromTeamName,MovedFromPostId(de pointer),MovedFromPermalinken, voor een publiek bronkanaal,MovedFromChannelNameenMovedFromChannelDisplayName.
Beide hebben ook een TranslationID. De naam van een privé-kanaal wordt weggelaten: lezers zien "ander kanaal". Mattermosts eigen POST /posts/{post_id}/move is in Antimatter uitgeschakeld; gebruik deze endpoint.
Modelverbindingen
Een modelverbinding is het adres en de sleutel van een AI-aanbieder, ingesteld door een beheerder. De AI-functies van de server en de apps die de AI-dienst aanroepen, gebruiken ze. Systeembeheerders beheren de serverbrede verbindingen (manage_ai_connections); de beheerders van een community beheren die van hun eigen community (manage_team_ai_connections). Sleutels zijn alleen-schrijfbaar: geen antwoord bevat er een, alleen api_key_set en api_key_last4.
| Eindpunt | Wat het doet |
|---|---|
GET /ai/connections?scope= | De verbindingen die u beheert. scope is server of het ID van een community; zonder dit veld, alle scopes die u beheert. |
POST /ai/connections | Voegt een verbinding toe (antwoordt 201). |
POST /ai/connections/test, POST /ai/connections/models | Test een verbinding of toont de modellen ervan, voordat deze wordt opgeslagen. Zelfde body als bij toevoegen; er wordt niets opgeslagen. |
GET, PATCH (of PUT), DELETE /ai/connections/{connection_id} | Leest, wijzigt of verwijdert een verbinding. Een patch bevat alleen de velden die gewijzigd moeten worden; laat api_key weg om de sleutel te behouden. |
POST /ai/connections/{connection_id}/test | Test een opgeslagen verbinding: {"ok", "error", "status_code", "latency_ms", "model_count"}. |
GET /ai/connections/{connection_id}/models | De modellen die de provider aanbiedt. |
GET /ai/connections/{connection_id}/usage | De verzoeken en tokens van deze maand. |
GET /ai/connections/usable?channel_id=&team_id= | Voor iedereen die is aangemeld: de verbindingen die u daar kunt gebruiken, met hun modellen en mogelijkheden, nooit hun sleutels of adressen. |
De inhoud van een nieuwe verbinding:
{
"name": "Local models",
"scope": "server",
"provider": "openai_compatible",
"base_url": "http://llm.internal:8000/v1",
"api_key": "…",
"extra_headers": {},
"models": {"chat": "qwen3-32b", "embeddings": "", "transcription": "", "decisions": ""},
"limits": {"requests_per_minute": 0, "monthly_token_budget": 0, "per_user_requests_per_minute": 0, "per_user_monthly_token_budget": 0},
"sharing": {"all_teams": true, "team_ids": []},
"audience": {"everyone": true, "group_ids": [], "roles": [], "allow_guests": false}
}
provider is openai_compatible of anthropic. scope is standaard server; het ID van een community maakt het de verbinding van die community. In limits betekent 0 geen limiet; verzoeken per minuut worden per server geteld, tokenbudgetten per kalendermaand (UTC) voor het hele cluster. sharing bepaalt welke communities een serverbrede verbinding mogen gebruiken (privé- en groepsberichten vereisen all_teams), en audience wie het mag gebruiken; gasten alleen met allow_guests. Wijzigingen worden in de auditlog geschreven. De beheerdersgids legt de instellingen uit: zie AI.