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 id van 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 een team_id.
  • jezelf: overal waar een pad een user_id verwacht, betekent me de aangemelde gebruiker, zoals in GET /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:

  1. Een systeembeheerder schakelt Persoonlijke toegangstokens inschakelen in via Systeemconsole › Integraties › Integratiebeheer (ServiceSettings.EnableUserAccessTokens, AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS).
  2. 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.
  3. 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.

Browsers authenticeren met een cookie in plaats daarvan. Een verzoek dat is geauthenticeerd via de cookie moet voor alles behalve GET ook de 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:

  1. Aanzetten van OAuth 2.0 Service Provider moet ingeschakeld zijn (Systeemconsole › Integraties › Integratiebeheer, ServiceSettings.EnableOAuthServiceProvider, standaard ingeschakeld).
  2. 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.
  3. Uw applicatie stuurt mensen door naar https://chat.example.com/oauth/authorize met response_type=code, client_id, redirect_uri en state. PKCE met code_challenge_method=S256 wordt ondersteund.
  4. Daarna wisselt het de code in bij POST https://chat.example.com/oauth/access_token (grant_type=authorization_code, en daarna refresh_token om te vernieuwen) en roept het de API aan met Authorization: Bearer <access token>.

Gebruikers zien de apps waaraan ze toegang hebben gegeven in Profiel & instellingen › Beveiliging › Apps waaraan je toegang hebt gegeven.

Belangrijkste bronnen

WatEndpoints
U en andere mensenGET /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=…
GemeenschappenGET /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
KanalenGET /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
BerichtenPOST /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
ReactiesPOST /reactions met {"user_id", "post_id", "emoji_name"}, DELETE /users/{user_id}/posts/{post_id}/reactions/{emoji_name}
BestandenPOST /files (multipart: channel_id en files), en voeg de teruggegeven IDs toe aan file_ids van het bericht; GET /files/{file_id}
VoorkeurenGET /users/me/preferences, PUT /users/me/preferences
Integraties/hooks/incoming, /hooks/outgoing, /commands, /bots, /oauth/apps (zie de volgende pagina's)
ServerGET /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.Client4 in server/public/model (import github.com/mattermost/mattermost/server/public/model). model.NewAPIv4Client(url), daarna client.SetToken(token); model.NewWebSocketClient4(wsURL, token) volgt gebeurtenissen. De kopie van Antimatter voegt methoden toe voor de eigen eindpunten, zoals UpdateMessageRequest, PutPostOnTop en ExportChannel.
  • TypeScript: de Client4-klasse van @mattermost/client, te vinden in webapp/platform/client, met de bijbehorende types in webapp/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.

EindpuntWat het doet
GET /teams/{team_id}/user_attributes/fields
POST zelfde pad
PATCH, 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_attributes
PATCH zelfde pad
POST /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}/timeouts
PUT /teams/{team_id}/members/{user_id}/timeout
GET /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_top
PUT, 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_requestWerkt 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}/overrides
GET /channels/{channel_id}/overrides/effective
GET, 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_categories
GET, 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_role
PUT …/team_role/permissions
De rechten die een communityrol verleent.
POST /teams/{team_id}/autolinks/previewTest 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}/speechDe boodschap die als audio wordt voorgelezen wanneer tekst-naar-spraak is geconfigureerd.
POST /posts/{post_id}/move_to_channelVerplaatst een draadje naar een ander kanaal in dezelfde community: zie Een draadje verplaatsen.
GET, POST /ai/connections
GET, 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_actions
POST /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, en PUT /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 (community of workplace: in een workplace kunnen kanaalbeheerders hun kanalen ook archiveren; nieuwe communities krijgen het TeamSettings.DefaultCommunityKind van de server, standaard community), member_list_view (hoe de ledenlijst leden groepeert: choice, de standaard, laat elk lid kiezen; roles of teams is vast), hide_role_colors, require_team_badges, onboarding en autolinks (beide JSON-strings).
  • Het standaardkanaal van een nieuwe community is general (Algemeen), niet town-square. De upgrade naar 0.9.0 hernoemt het town-square-kanaal van elke community naar general, waarbij de ID behouden blijft, tenzij de community al een general-kanaal heeft. De oude namen blijven werken: GET /teams/{team_id}/channels/name/town-square, GET /teams/name/{team}/channels/name/town-square en het channel-veld van een inkomende webhook geven het standaardkanaal van de community terug als er geen kanaal met die naam bestaat. Gebruik in nieuwe code default_channel_id of de naam general.
  • Kanaallinks: #channel-name koppelt een kanaal, net zoals ~channel-name. De channel_mentions-eigenschap van het bericht toont de kanalen die op die manier zijn gekoppeld; een #word zonder 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": false toe om de auteur niet te verwittigen. De server vult metadata.reply_to in 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 waarde ignore of block. Of een privébericht als verzoek wacht, staat in notify_props.dm_request van uw kanaallid (pending, accepted of dismissed).
  • Berichtbijlagen kunnen stages en een chart bevatten: 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 (standaard false): true maakt 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 403 met de ID api.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.MoveThreadMaxCount berichten (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, MovedThreadPostId en, voor een publiek doelkanaal, MovedThreadChannelName en MovedThreadChannelDisplayName.
  • De notitie: MovedFromChannelId, MovedFromTeamName, MovedFromPostId (de pointer), MovedFromPermalink en, voor een publiek bronkanaal, MovedFromChannelName en MovedFromChannelDisplayName.

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.

EindpuntWat 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/connectionsVoegt een verbinding toe (antwoordt 201).
POST /ai/connections/test, POST /ai/connections/modelsTest 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}/testTest een opgeslagen verbinding: {"ok", "error", "status_code", "latency_ms", "model_count"}.
GET /ai/connections/{connection_id}/modelsDe modellen die de provider aanbiedt.
GET /ai/connections/{connection_id}/usageDe 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.