#pApiAuth
Référence complète des champs API & CLI : les 12 types d'objets, les endpoints REST & POST /api/v1/send
Cette référence documente chaque propriété JSON, type de données, valeur d'énumération, valeur par défaut et rôle RBAC minimal des 12 objets de gestion (/api/admin/cli/objects/{type} & nextxch-cli), ainsi que la remise d'e-mails transactionnels (POST /api/v1/send). Utilisez le champ de filtre instantané au-dessus du tableau pour rechercher une propriété comme dkimSigningMode, tlsMode, allowedCidrs ou warmingEnabled.
Introspection en direct dans votre terminal ou via HTTP : chaque nextxch expose ce schéma complet en JSON lisible par machine sous GET /api/admin/cli/schema (avec l'en-tête SHA-256 X-Nextxch-Schema-Version). Dans votre terminal, exécutez à tout moment nextxch-cli describe <Type> (par ex. nextxch-cli describe Domain ou nextxch-cli describe SmtpQueue).
TransactionalSendRequest (POST /api/v1/send)
13
IntegrationKey (API v1)
9
CalendarEvent (API v1)
12
Rooms & Booking (API v1)
6
Contact, Directory & Sharing (API v1)
9
Webhook (API v1)
4
Tenant
11
Domain
19
Account (Account/User & Account/List)
18
Alias
7
ApiKey
11
Route
10
TransactionalSend (Singleton)
11
ReputationShield (Singleton)
20
SpamGuard (Singleton)
15
SmtpQueue (Singleton)
19
TransportRules & Server (Singletons)
11
TransactionalSendRequest (POST /api/v1/send)
Clé : Idempotency-Key
RBAC : User+
Point de terminaison HTTP JSON à haut débit pour la remise d'e-mails depuis applications web, ERP, CRM et codes 2FA, avec priorisation par catégorie, préchauffage d'IP, pré-vérification de suppression et idempotence sur 24 h.
/api/v1/send
Met en file d'attente et signe un e-mail transactionnel (UTF-8 Multipart/Alternative + pièces jointes)
/api/v1/unsubscribe/{token}
Point de terminaison public de désabonnement en un clic RFC 8058 (jeton signé DKIM)
from
string
FACULTATIF
Key senderAddress
to
string[]
OBLIGATOIRE
cc
string[]
FACULTATIF
[]
bcc
string[]
FACULTATIF
[]
replyTo
string
FACULTATIF
subject
string
OBLIGATOIRE
textBody
string
FACULTATIF
htmlBody
string
FACULTATIF
category
string
FACULTATIF
transactional
"critical""transactional""notification""marketing"overflowMode
string
FACULTATIF
DeferQueue
"DeferQueue""Reject429"idempotencyKey
string
FACULTATIF
Header Idempotency-Key
headers
Record<string, string>
FACULTATIF
{}
attachments
SendAttachmentDto[]
FACULTATIF
[]
{
"from": "Abrechnung <rechnung@firma.de>",
"to": ["einkauf@kunde.de"],
"cc": ["buchhaltung@firma.de"],
"subject": "Ihre elektronische Rechnung RE-2026-90412",
"category": "transactional",
"overflowMode": "DeferQueue",
"textBody": "Guten Tag,\nanbei erhalten Sie Ihre Rechnung RE-2026-90412.",
"htmlBody": "<p>Guten Tag,</p><p>anbei erhalten Sie Ihre Rechnung <strong>RE-2026-90412</strong>.</p>",
"headers": {
"X-ERP-Document-Id": "RE-2026-90412"
},
"attachments": [
{
"fileName": "RE-2026-90412.pdf",
"contentType": "application/pdf",
"base64Content": "JVBERi0xLjcKJcfs..."
}
]
}
# 1) Kleinstprivilegierten Sende-Key (Role=User) für rechnung@firma.de erstellen:
nextxch-cli create ApiKey \
--set label="ERP Rechnungsversand" \
--set role=User \
--set senderAddress=rechnung@firma.de \
--set defaultCategory=transactional \
--set allowedCidrs=10.20.0.0/16
# 2) Risikofreier Trockentest gegen die integrierte Sandbox-Sink-Domain:
# ok@sink.nextxch.local | bounce@sink.nextxch.local | defer@sink.nextxch.local
curl -fsS -X POST "https://mail.firma.de/api/v1/send" \
-H "Authorization: Bearer smk_01968f2a_..." \
-H "Idempotency-Key: inv-2026-90412" \
-H "Content-Type: application/json" \
-d '{
"from": "rechnung@firma.de",
"to": ["einkauf@kunde.de"],
"subject": "Ihre Rechnung RE-2026-90412",
"category": "transactional",
"textBody": "Guten Tag, anbei Ihre Rechnung RE-2026-90412.",
"htmlBody": "<p>Guten Tag, anbei Ihre Rechnung <b>RE-2026-90412</b>.</p>"
}'
using System.Net.Http.Headers;
using System.Net.Http.Json;
using var http = new HttpClient { BaseAddress = new Uri("https://mail.firma.de") };
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "smk_01968f2a_...");
http.DefaultRequestHeaders.Add("Idempotency-Key", "inv-2026-90412");
var response = await http.PostAsJsonAsync("/api/v1/send", new
{
from = "rechnung@firma.de",
to = new[] { "einkauf@kunde.de" },
subject = "Ihre Rechnung RE-2026-90412",
category = "transactional",
textBody = "Guten Tag, anbei Ihre Rechnung RE-2026-90412.",
htmlBody = "<p>Guten Tag, anbei Ihre Rechnung <strong>RE-2026-90412</strong>.</p>"
});
response.EnsureSuccessStatusCode();
IntegrationKey (API v1)
Clé : id
RBAC : TenantAdmin+
Clé d'intégration avec scopes pour /api/v1. Une clé agit pour un utilisateur ou, en tant qu'intégration de locataire, pour l'utilisateur indiqué dans l'en-tête X-Nextxch-Act-As. Sans le scope, l'API répond 403 ; un utilisateur d'un autre locataire donne 404. Client credentials OAuth 2.0 en option (jeton valable 1 heure).
/api/admin/integrations/keys
Créer une clé (admin, affichée une seule fois)
/api/admin/integrations/keys/{id}
Modifier les portées
/api/admin/integrations/keys/{id}
Révoquer une clé (et ses jetons OAuth)
/api/v1/oauth/token
OAuth 2.0 client_credentials : ID de clé + clé pour obtenir un jeton d'accès
/api/v1/me
Clé, scopes et utilisateur agissant
/api/v1/openapi.json
Document OpenAPI 3.1 de l'installation
label
string
OBLIGATOIRE
mode
string
OBLIGATOIRE
user
"user""tenant"userEmail
string
FACULTATIF
scopes
string[]
OBLIGATOIRE
"calendar.read""calendar.write""rooms.read""booking.read""booking.write""contacts.read""contacts.write""directory.read""sharing.manage""webhooks.manage""mail.send"domainId
guid
FACULTATIF
allowedCidrs
string[]
FACULTATIF
[]
expiresInDays
integer
FACULTATIF
senderAddress
string
FACULTATIF
apiKey
string
LECTURE SEULE
{
"label": "CRM",
"mode": "tenant",
"scopes": ["calendar.write", "rooms.read", "contacts.write", "webhooks.manage"],
"allowedCidrs": ["203.0.113.0/24"],
"expiresInDays": 365
}
# Integrations-Schlüssel: Admin > API & Integrationen > Neuer Schlüssel
# Danach z. B. ein Access-Token per OAuth 2.0 Client Credentials holen:
curl -fsS -X POST "https://mail.firma.de/api/v1/oauth/token" \
-d grant_type=client_credentials \
-d client_id=0196c3a2-5f1e-7c11-9a20-1c2d3e4f5a6b \
-d client_secret=smk_0196c3a25f1e7c119a201c2d3e4f5a6b_... \
-d scope="calendar.read rooms.read"
curl -fsS "https://mail.firma.de/api/v1/me" \
-H "Authorization: Bearer smk_0196c3a2..." \
-H "X-Nextxch-Act-As: anna@firma.de"
using var http = new HttpClient { BaseAddress = new Uri("https://mail.firma.de") };
http.DefaultRequestHeaders.Authorization = new("Bearer", "smk_0196c3a2...");
http.DefaultRequestHeaders.Add("X-Nextxch-Act-As", "anna@firma.de");
var me = await http.GetFromJsonAsync<JsonElement>("/api/v1/me");
CalendarEvent (API v1)
Clé : hrefName
RBAC : User+
Événements avec séries et exceptions, participants, salles, invitations, réponses, disponibilité, calendriers partagés et globaux et liens d'invitation. Scopes calendar.read et calendar.write. Heures en UTC (ISO-8601), fuseaux horaires sous forme de noms IANA.
/api/v1/calendars
Calendriers personnels, partagés, globaux et de ressources
/api/v1/calendar/events?from&to&calendarId&limit&cursor
Occurrences dans une fenêtre (séries développées)
/api/v1/calendar/events
Créer un événement (inviter des personnes et des salles)
/api/v1/calendar/events/{hrefName}
Événement avec série et exceptions
/api/v1/calendar/events/{hrefName}
Modifier ; scope=occurrence|following pour des parties d'une série
/api/v1/calendar/events/{hrefName}
Supprimer, avec annulations facultatives (notify=true)
/api/v1/calendar/events/{hrefName}/respond
Répondre à une invitation
/api/v1/calendar/events/{hrefName}/invite-link
Lien d'invitation signé
/api/v1/calendar/events/{hrefName}/ics
iCalendar brut
/api/v1/calendar/freebusy
Disponibilité des personnes et des salles
title
string
OBLIGATOIRE
startUtc
datetime
OBLIGATOIRE
endUtc
datetime
OBLIGATOIRE
timeZone
string
FACULTATIF
Europe/Berlin
allDay
boolean
FACULTATIF
false
attendees
Attendee[]
FACULTATIF
[]
sendInvitations
boolean
FACULTATIF
false
recurrence
Récurrence
FACULTATIF
showAs
string
FACULTATIF
busy
"free""tentative""busy""oof""workingElsewhere"isPrivate
boolean
FACULTATIF
false
calendarId
string
FACULTATIF
teamsMeeting
boolean
FACULTATIF
{
"title": "Projektstart",
"startUtc": "2026-12-03T09:00:00Z",
"endUtc": "2026-12-03T10:00:00Z",
"timeZone": "Europe/Berlin",
"attendees": [
{ "email": "bernd@firma.de" },
{ "email": "raum-1@firma.de" }
],
"sendInvitations": true
}
# Benötigte Scopes: calendar.read (lesen), calendar.write (schreiben)
# Einen Raum buchen: Raumadresse als Teilnehmer eintragen
curl -fsS -X POST "https://mail.firma.de/api/v1/calendar/events" \
-H "Authorization: Bearer smk_0196c3a2..." \
-H "X-Nextxch-Act-As: anna@firma.de" \
-H "Content-Type: application/json" \
-d '{"title":"Projektstart","startUtc":"2026-12-03T09:00:00Z","endUtc":"2026-12-03T10:00:00Z","timeZone":"Europe/Berlin","attendees":[{"email":"raum-1@firma.de"}]}'
var res = await http.PostAsJsonAsync("/api/v1/calendar/events", new
{
title = "Projektstart",
startUtc = DateTimeOffset.Parse("2026-12-03T09:00:00Z"),
endUtc = DateTimeOffset.Parse("2026-12-03T10:00:00Z"),
timeZone = "Europe/Berlin",
attendees = new[] { new { email = "raum-1@firma.de" } }
});
string href = (await res.Content.ReadFromJsonAsync<JsonElement>()).GetProperty("data").GetProperty("hrefName").GetString()!;
Rooms & Booking (API v1)
Clé : id
RBAC : User+
Salles et ressources avec disponibilité (rooms.read) et pages de réservation à la Calendly (booking.read, booking.write) : page de réservation, types d'événements, créneaux libres, lecture et annulation des réservations. Une salle est réservée via un événement dont elle est participante.
/api/v1/rooms?startUtc&endUtc&category
Salles et ressources, avec leur disponibilité sur la période
/api/v1/rooms/{email}/availability
Créneaux occupés d'une salle
/api/v1/booking/profile
Page de réservation avec horaires et types d'événements
/api/v1/booking/event-types
Types d'événements
/api/v1/booking/event-types
Créer un type d'événement
/api/v1/booking/event-types/{id}/slots?from&to
Heures de début libres (42 jours max.)
/api/v1/booking/bookings?status&from&to
Réservations
/api/v1/booking/bookings/{id}/cancel
Annuler une réservation (l'invité est informé)
slots[].startUtc
datetime
LECTURE SEULE
slots[].endUtc
datetime
LECTURE SEULE
slots[].staff
object[]
LECTURE SEULE
status
string
LECTURE SEULE
"confirmed""cancelled"guest
object
LECTURE SEULE
free
boolean
LECTURE SEULE
{
"ok": true,
"data": {
"eventTypeId": "beratung-3f2a",
"durationMinutes": 30,
"timeZone": "Europe/Berlin",
"slots": [
{ "startUtc": "2026-12-04T08:00:00Z", "endUtc": "2026-12-04T08:30:00Z", "staff": [] }
]
}
}
# Benötigte Scopes: rooms.read, booking.read, booking.write
curl -fsS "https://mail.firma.de/api/v1/rooms?startUtc=2026-12-03T09:00:00Z&endUtc=2026-12-03T10:00:00Z" \
-H "Authorization: Bearer smk_0196c3a2..."
var slots = await http.GetFromJsonAsync<JsonElement>("/api/v1/booking/event-types/beratung/slots");
foreach (var s in slots.GetProperty("data").GetProperty("slots").EnumerateArray())
Console.WriteLine(s.GetProperty("startUtc").GetString());
Contact, Directory & Sharing (API v1)
Clé : hrefName
RBAC : User+
Contacts personnels avec tous les champs et photo (contacts.read, contacts.write, If-Match pour la protection contre les conflits), liste d'adresses globale (directory.read) ainsi que partages et délégation (sharing.manage, délégation = autorisation sur la boîte aux lettres avec sendAs ou sendOnBehalf).
/api/v1/contacts?q
Rechercher des contacts
/api/v1/contacts
Créer un contact
/api/v1/contacts/{hrefName}
Modifier un contact (les champs null restent inchangés)
/api/v1/contacts/{hrefName}
Supprimer un contact
/api/v1/directory?q&type
Liste d'adresses globale
/api/v1/sharing/grants
Autorisations propres
/api/v1/sharing/grants
Définir ou supprimer une autorisation
/api/v1/sharing/shared-with-me
Partagés avec moi
givenName
string
FACULTATIF
familyName
string
FACULTATIF
organization
string
FACULTATIF
emails
TypedValue[]
FACULTATIF
[]
phones
TypedValue[]
FACULTATIF
[]
addresses
Address[]
FACULTATIF
[]
birthday
string
FACULTATIF
photo
string
ÉCRITURE SEULE (SECRET)
permissions
string[]
FACULTATIF
"freeBusy""read""write""delete""sendOnBehalf""sendAs""manage"{
"givenName": "Clara",
"familyName": "Kunde",
"organization": "Kunde AG",
"emails": [{ "type": "work", "value": "clara@kunde.example" }],
"phones": [{ "type": "cell", "value": "+49 170 1234567" }]
}
# Benötigte Scopes: contacts.read, contacts.write, directory.read, sharing.manage
curl -fsS -X POST "https://mail.firma.de/api/v1/contacts" \
-H "Authorization: Bearer smk_0196c3a2..." \
-H "Content-Type: application/json" \
-d '{"givenName":"Clara","familyName":"Kunde","emails":[{"type":"work","value":"clara@kunde.example"}]}'
await http.PutAsJsonAsync("/api/v1/sharing/grants", new
{
kind = "calendar", granteeType = "user", grantee = "bernd@firma.de", permissions = new[] { "read" }
});
Webhook (API v1)
Clé : id
RBAC : User+
Événements sous forme de POST JSON signé : calendar.event.created, calendar.event.updated, calendar.event.deleted, calendar.invitation.replied, booking.created, booking.rescheduled, booking.cancelled. Signature X-Nextxch-Signature: v1=hex(HMAC-SHA256(secret, X-Nextxch-Timestamp + "." + body)). Nouvelles tentatives après 30 s, 2 min, 10 min, 1 h et 6 h.
/api/v1/webhooks
Webhooks du locataire
/api/v1/webhooks
Enregistrer un webhook (secret uniquement dans la réponse)
/api/v1/webhooks/{id}
Supprimer un webhook
/api/v1/webhooks/{id}/deliveries
Remises récentes
/api/v1/webhooks/{id}/test
Envoyer un événement de test
url
string
OBLIGATOIRE
events
string[]
OBLIGATOIRE
"calendar.event.created""calendar.event.updated""calendar.event.deleted""calendar.invitation.replied""booking.created""booking.rescheduled""booking.cancelled""*"secret
string
LECTURE SEULE
id (Ereignis)
string
LECTURE SEULE
{
"id": "evt_5c1f0e9a2b7d4c3e8f601a2b",
"type": "calendar.invitation.replied",
"createdAtUtc": "2026-12-01T10:15:02Z",
"tenantId": "0196c3a2-0000-7000-8000-000000000001",
"data": {
"calendarId": "0196c3a25f1e7c11:default",
"hrefName": "0196c3a2@nextxch.ics",
"title": "Projektstart",
"startUtc": "2026-12-03T09:00:00Z",
"attendee": { "email": "bernd@firma.de", "partStat": "ACCEPTED" }
}
}
# Signatur prüfen (Bash):
# expected="v1=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)"
curl -fsS -X POST "https://mail.firma.de/api/v1/webhooks" \
-H "Authorization: Bearer smk_0196c3a2..." \
-H "Content-Type: application/json" \
-d '{"url":"https://crm.firma.de/hooks/nextxch","events":["calendar.event.created","booking.created"]}'
// ASP.NET Core receiver
app.MapPost("/hooks/nextxch", async (HttpRequest req) =>
{
using var ms = new MemoryStream();
await req.Body.CopyToAsync(ms);
string ts = req.Headers["X-Nextxch-Timestamp"]!;
byte[] mac = HMACSHA256.HashData(Encoding.UTF8.GetBytes(secret), [.. Encoding.ASCII.GetBytes(ts + "."), .. ms.ToArray()]);
return req.Headers["X-Nextxch-Signature"] == "v1=" + Convert.ToHexStringLower(mac) ? Results.Ok() : Results.Unauthorized();
});
Tenant
Clé : slug
RBAC : ServerAdmin+
Limite organisationnelle multi-locataire isolant les domaines, les principaux, les quotas de stockage (Gio) et la conservation de conformité GoBD WORM par défaut.
/api/admin/cli/objects/Tenant
Liste tous les locataires
/api/admin/cli/objects/Tenant/{slugOrId}
Récupère un locataire par slug ou UUID
/api/admin/cli/objects/Tenant
Crée un nouveau locataire
/api/admin/cli/objects/Tenant/{slugOrId}
Met à jour les quotas du locataire sur place
id
guid
LECTURE SEULE
UUIDv7
slug
string
PRIMARY KEY
name
string
OBLIGATOIRE
isActive
boolean
FACULTATIF
true
maxDomains
integer
FACULTATIF
100
maxPrincipals
integer
FACULTATIF
10000
quotaGb
integer
FACULTATIF
100
outboundDailyLimit
integer
FACULTATIF
25000
defaultLockMode
string
FACULTATIF
Normal
"Normal""Governance""Compliance""LegalHold"defaultRetentionDays
integer
FACULTATIF
0
createdAtUtc
datetime
LECTURE SEULE
{
"slug": "acme",
"name": "ACME Logistik GmbH",
"isActive": true,
"maxDomains": 50,
"maxPrincipals": 2500,
"quotaGb": 250,
"outboundDailyLimit": 25000,
"defaultLockMode": "Compliance",
"defaultRetentionDays": 3650
}
# Mandant anlegen:
nextxch-cli create Tenant \
--set slug=acme \
--set name="ACME Logistik GmbH" \
--set quotaGb=250 \
--set defaultLockMode=Compliance \
--set defaultRetentionDays=3650
# Mandant abfragen & Kontingent erhöhen:
nextxch-cli get Tenant acme
nextxch-cli update Tenant acme --set quotaGb=500
curl -fsS -X POST "https://mail.firma.de/api/admin/cli/objects/Tenant" \
-H "Authorization: Bearer smk_..." \
-H "Content-Type: application/json" \
-d '{"slug":"acme","name":"ACME Logistik GmbH","quotaGb":250,"defaultLockMode":"Compliance","defaultRetentionDays":3650}'
var payload = new
{
slug = "acme",
name = "ACME Logistik GmbH",
quotaGb = 250,
defaultLockMode = "Compliance",
defaultRetentionDays = 3650
};
using var res = await http.PostAsJsonAsync("/api/admin/cli/objects/Tenant", payload);
Domain
Clé : name
RBAC : TenantAdmin+
Domaine de messagerie hébergé avec génération parallèle automatique des clés Dual-DKIM (RSA-2048 + Ed25519), politique de conservation GoBD WORM, plus-addressing et limites de débit.
/api/admin/cli/objects/Domain
Liste tous les domaines
/api/admin/cli/objects/Domain/{name}
Récupère la configuration du domaine & les sélecteurs DKIM
/api/admin/cli/objects/Domain
Crée le domaine & génère les clés DKIM RSA-2048 + Ed25519
/api/admin/cli/objects/Domain/{name}
Met à jour le mode DKIM, les quotas ou la conservation en 0 ms
/api/admin/cli/dns/{name}?live=true
Vérifie les enregistrements DNS en direct ou exporte une zone BIND RFC 1035
id
guid
LECTURE SEULE
UUIDv7
name
string
PRIMARY KEY
tenant
string
FACULTATIF
default
isActive
boolean
FACULTATIF
true
postmasterAddress
string
FACULTATIF
postmaster@<name>
dkimSigningMode
string
FACULTATIF
Dual
"Rsa2048""Ed25519""Dual"dkimRsaSelector
string
FACULTATIF
s2026
dkimRsaDnsName
string
LECTURE SEULE
s2026._domainkey.<name>
dkimEd25519Selector
string
FACULTATIF
ed2026
dkimEd25519DnsName
string
LECTURE SEULE
ed2026._domainkey.<name>
retentionLockMode
string
FACULTATIF
Normal
"Normal""Governance""Compliance""LegalHold"retentionDays
integer
FACULTATIF
0
quotaGb
integer
FACULTATIF
50
maxMessageSizeMb
integer
FACULTATIF
50
maxAccounts
integer
FACULTATIF
1000
outboundDailyLimit
integer
FACULTATIF
5000
outboundHourlyLimit
integer
FACULTATIF
1000
usePlusAddressing
boolean
FACULTATIF
true
createdAtUtc
datetime
LECTURE SEULE
{
"name": "muster-logistik.de",
"tenant": "default",
"isActive": true,
"postmasterAddress": "postmaster@muster-logistik.de",
"dkimSigningMode": "Dual",
"dkimRsaSelector": "s2026",
"dkimEd25519Selector": "ed2026",
"retentionLockMode": "Compliance",
"retentionDays": 3650,
"quotaGb": 100,
"maxMessageSizeMb": 50,
"maxAccounts": 500,
"outboundDailyLimit": 10000,
"outboundHourlyLimit": 2000,
"usePlusAddressing": true
}
# Domain mit Dual-DKIM und 10 Jahren GoBD-Compliance anlegen:
nextxch-cli create Domain \
--set name=muster-logistik.de \
--set dkimSigningMode=Dual \
--set retentionLockMode=Compliance \
--set retentionDays=3650
# Fertige RFC-1035 BIND-Zonendatei exportieren & DNS live prüfen:
nextxch-cli dns muster-logistik.de --bind > muster-logistik.de.zone
nextxch-cli dns muster-logistik.de --live
curl -fsS -X PATCH "https://mail.firma.de/api/admin/cli/objects/Domain/muster-logistik.de" \
-H "Authorization: Bearer smk_..." \
-H "Content-Type: application/json" \
-d '{"dkimSigningMode":"Dual","retentionLockMode":"Compliance","retentionDays":3650}'
using var res = await http.PatchAsJsonAsync(
"/api/admin/cli/objects/Domain/muster-logistik.de",
new { dkimSigningMode = "Dual", quotaGb = 200 });
res.EnsureSuccessStatusCode();
Account (Account/User & Account/List)
Clé : email
RBAC : TenantAdmin+
Représente une boîte aux lettres utilisateur (@type="User", avec IMAP/JMAP/CalDAV/CardDAV/ActiveSync) ou une liste de distribution (@type="List" avec members[]).
/api/admin/cli/objects/Account?filter=role=TenantAdmin
Liste/filtre les comptes et listes de distribution
/api/admin/cli/objects/Account/User
Crée une nouvelle boîte aux lettres utilisateur avec les dossiers RFC 6154
/api/admin/cli/objects/Account/List
Crée une nouvelle liste de distribution
/api/admin/cli/objects/Account/{email}
Met à jour le quota, le transfert, l'absence ou le mot de passe
/api/admin/cli/objects/Account/{email}
Supprime un compte de manière réversible (soft delete)
id
guid
LECTURE SEULE
UUIDv7
@type
string
FACULTATIF
User
"User""List"email
string
PRIMARY KEY
displayName
string
FACULTATIF
Lokalteil
password
string
ÉCRITURE SEULE (SECRET)
role
string
FACULTATIF
User
"User""ComplianceAuditor""TenantAdmin""ServerAdmin"isActive
boolean
FACULTATIF
true
quotaMb
integer
FACULTATIF
5120
usedBytes
long
LECTURE SEULE
0
outboundDailyLimit
integer
FACULTATIF
500
forwardAddress
string
FACULTATIF
forwardKeepOriginal
boolean
FACULTATIF
true
vacationEnabled
boolean
FACULTATIF
false
vacationSubject
string
FACULTATIF
vacationBody
string
ÉCRITURE SEULE (SECRET)
twoFactorEnabled
boolean
LECTURE SEULE
false
members
string[]
FACULTATIF
[]
createdAtUtc
datetime
LECTURE SEULE
{
"@type": "User",
"email": "anna.weber@muster-logistik.de",
"displayName": "Anna Weber (IT-Leitung)",
"password": "SicheresStartPasswort!2026",
"role": "TenantAdmin",
"isActive": true,
"quotaMb": 15360,
"outboundDailyLimit": 1000,
"forwardAddress": null,
"forwardKeepOriginal": true,
"vacationEnabled": false,
"vacationSubject": "Abwesenheitsnotiz: Anna Weber",
"vacationBody": "Ich bin ab Montag wieder erreichbar."
}
# Benutzerpostfach (15 GiB Quota) anlegen:
nextxch-cli create Account/User \
--set email=anna.weber@muster-logistik.de \
--set displayName="Anna Weber" \
--set password="SicheresStartPasswort!2026" \
--set quotaMb=15360
# Verteilerliste anlegen:
nextxch-cli create Account/List \
--set email=team@muster-logistik.de \
--set displayName="Disposition & Einkauf" \
--set members=anna.weber@muster-logistik.de,dispo@muster-logistik.de
curl -fsS -X POST "https://mail.firma.de/api/admin/cli/objects/Account/User" \
-H "Authorization: Bearer smk_..." \
-H "Content-Type: application/json" \
-d '{"email":"anna.weber@muster-logistik.de","displayName":"Anna Weber","password":"SicheresStartPasswort!2026","quotaMb":15360}'
await http.PostAsJsonAsync("/api/admin/cli/objects/Account/User", new
{
email = "anna.weber@muster-logistik.de",
displayName = "Anna Weber",
password = "SicheresStartPasswort!2026",
quotaMb = 15360
});
Alias
Clé : address
RBAC : TenantAdmin+
Alias e-mail secondaire ou alias de confidentialité masqué jetable, acheminé vers une boîte aux lettres Account principale ou une liste de distribution.
/api/admin/cli/objects/Alias
Liste tous les alias et e-mails masqués
/api/admin/cli/objects/Alias
Crée un nouvel alias acheminé vers une boîte aux lettres cible
/api/admin/cli/objects/Alias/{address}
Active/suspend un alias ou met à jour sa cible
/api/admin/cli/objects/Alias/{address}
Supprime l'alias
address
string
PRIMARY KEY
target
string
OBLIGATOIRE
principalId
guid
LECTURE SEULE
description
string
FACULTATIF
""
isMasked
boolean
FACULTATIF
false
isEnabled
boolean
FACULTATIF
true
createdAtUtc
datetime
LECTURE SEULE
{
"address": "shop-8f2k@muster-logistik.de",
"target": "anna.weber@muster-logistik.de",
"description": "Fachbuchhandlung / Online-Bestellung",
"isMasked": true,
"isEnabled": true
}
# Masked-Email-Alias anlegen:
nextxch-cli create Alias \
--set address=shop-8f2k@muster-logistik.de \
--set target=anna.weber@muster-logistik.de \
--set description="Fachbuchhandlung" \
--set isMasked=true
# Alias bei Spam-Aufkommen mit 1 Befehl stummschalten:
nextxch-cli update Alias shop-8f2k@muster-logistik.de --set isEnabled=false
curl -fsS -X POST "https://mail.firma.de/api/admin/cli/objects/Alias" \
-H "Authorization: Bearer smk_..." \
-H "Content-Type: application/json" \
-d '{"address":"vertrieb@muster-logistik.de","target":"anna.weber@muster-logistik.de","description":"Vertrieb & Angebote"}'
await http.PostAsJsonAsync("/api/admin/cli/objects/Alias", new
{
address = "vertrieb@muster-logistik.de",
target = "anna.weber@muster-logistik.de",
description = "Vertrieb & Angebote",
isEnabled = true
});
ApiKey
Clé : id
RBAC : TenantAdmin+
Clé API à portée limitée, immuable et restreinte par RBAC et CIDR (smk_<id>_<secret>) pour /api/v1/send, SCIM 2.0 ou nextxch-cli.
/api/admin/cli/objects/ApiKey
Liste les clés API actives (secret omis)
/api/admin/cli/objects/ApiKey
Génère une nouvelle clé d'API et renvoie apiKey (smk_...) une seule fois
/api/admin/cli/objects/ApiKey/{id}
Révoque immédiatement la clé d'API
id
guid
LECTURE SEULE
UUIDv7
apiKey
string
CRÉATION UNIQUEMENT
smk_<id>_<secret>
label
string
OBLIGATOIRE
role
string
FACULTATIF
TenantAdmin
"User""ComplianceAuditor""TenantAdmin""ServerAdmin"senderAddress
string
FACULTATIF
defaultCategory
string
FACULTATIF
transactional
"critical""transactional""notification""marketing"allowedCidrs
string[]
FACULTATIF
[] (Alle IPs)
expiresInDays
integer
ÉCRITURE SEULE (SECRET)
null (Kein Ablauf)
expiresAtUtc
datetime
LECTURE SEULE
outboundDailyLimit
integer
FACULTATIF
10000
isActive
boolean
LECTURE SEULE
true
{
"label": "Shopware 6 ERP Rechnungsversand",
"role": "User",
"senderAddress": "rechnung@muster-logistik.de",
"defaultCategory": "transactional",
"allowedCidrs": ["10.20.10.15/32", "2a01:4f8:120:44aa::/64"],
"expiresInDays": 180,
"outboundDailyLimit": 10000
}
# CIDR-geschützten Key für Ansible / nextxch-cli erstellen:
nextxch-cli create ApiKey \
--set label="GitLab CI / Ansible" \
--set role=TenantAdmin \
--set allowedCidrs=10.20.0.0/16 \
--set expiresInDays=90
# Schlüssel widerrufen:
nextxch-cli delete ApiKey 0195f2a0-8b14-7000-9a10-001122334455
curl -fsS -X POST "https://mail.firma.de/api/admin/cli/objects/ApiKey" \
-H "Authorization: Bearer smk_..." \
-H "Content-Type: application/json" \
-d '{"label":"Shopware 6","role":"User","senderAddress":"rechnung@muster-logistik.de","allowedCidrs":["10.20.10.15/32"],"expiresInDays":180}'
var res = await http.PostAsJsonAsync("/api/admin/cli/objects/ApiKey", new
{
label = "Shopware 6",
role = "User",
senderAddress = "rechnung@muster-logistik.de",
allowedCidrs = new[] { "10.20.10.15/32" },
expiresInDays = 180
});
var created = await res.Content.ReadFromJsonAsync<JsonElement>();
string oneTimeSecretKey = created.GetProperty("apiKey").GetString()!;
Route
Clé : domain
RBAC : ServerAdmin+
Routage SMTP sortant par domaine ou exception de certificat TLS (par ex. StartTlsIgnoreCert pour les hôtes MX partenaires aux certificats non concordants, ou connecteur smart host).
/api/admin/cli/objects/Route
Liste toutes les routes sortantes personnalisées
/api/admin/cli/objects/Route
Crée une route de domaine personnalisée ou une substitution TLS
/api/admin/cli/objects/Route/{domain}
Met à jour l'hôte cible, le port ou le mode TLS
/api/admin/cli/objects/Route/{domain}
Supprime la route personnalisée
domain
string
PRIMARY KEY
targetHost
string
FACULTATIF
"" (Auto DNS-MX)
targetPort
integer
FACULTATIF
25
tlsMode
string
FACULTATIF
StartTlsOptional
"StartTlsOptional""StartTlsRequired""StartTlsIgnoreCert""ImplicitTls""ImplicitTlsIgnoreCert""None"username
string
FACULTATIF
password
string
ÉCRITURE SEULE (SECRET)
hasPassword
boolean
LECTURE SEULE
false
clearPassword
boolean
ÉCRITURE SEULE (SECRET)
false
description
string
FACULTATIF
enabled
boolean
FACULTATIF
true
{
"domain": "neff.me",
"targetHost": "",
"targetPort": 25,
"tlsMode": "StartTlsIgnoreCert",
"username": null,
"description": "Shared-Hosting-MX mit abweichendem Zertifikatsnamen (Auto DNS-MX)",
"enabled": true
}
# Partner-Domain mit fehlerhaftem MX-Zertifikat per Auto-DNS-MX freigeben:
nextxch-cli create Route \
--set domain=neff.me \
--set tlsMode=StartTlsIgnoreCert \
--set description="TLS NameMismatch auf Partner-MX erlauben"
# Internes ERP-Subnetz an lokalen Connector routen:
nextxch-cli create Route \
--set domain=erp.firma.intern \
--set targetHost=10.40.2.15 \
--set targetPort=25
curl -fsS -X POST "https://mail.firma.de/api/admin/cli/objects/Route" \
-H "Authorization: Bearer smk_..." \
-H "Content-Type: application/json" \
-d '{"domain":"neff.me","targetHost":"","targetPort":25,"tlsMode":"StartTlsIgnoreCert","enabled":true}'
await http.PostAsJsonAsync("/api/admin/cli/objects/Route", new
{
domain = "neff.me",
targetHost = "",
targetPort = 25,
tlsMode = "StartTlsIgnoreCert",
enabled = true
});
TransactionalSend (Singleton)
Clé : singleton
RBAC : TenantAdmin+
Pilote la montée en charge IP progressive sur 28 jours, les catégories de messages et les quotas horaires/quotidiens par fournisseur destinataire (Google, Microsoft, Yahoo/AOL, FAI allemands, iCloud, *).
/api/admin/cli/objects/TransactionalSend/singleton
Récupère la montée en charge IP active & la politique de quotas fournisseurs
/api/admin/cli/objects/TransactionalSend/singleton
Met à jour le jour de montée en charge, le préréglage ou les quotas fournisseur
enabled
boolean
FACULTATIF
true
warmingEnabled
boolean
FACULTATIF
false
startAtWarmingDay
integer
ÉCRITURE SEULE (SECRET)
1
currentWarmingDay
integer
LECTURE SEULE
currentWarmingPercent
integer
LECTURE SEULE
warmingDailyRampPercents
integer[]
FACULTATIF
[5,7,10,...,100]
maxDeferHours
integer
FACULTATIF
48
defaultCategory
string
FACULTATIF
transactional
"critical""transactional""notification""marketing"preset
string
ÉCRITURE SEULE (SECRET)
"warming_28d""warming_14d""production_100"categories
CategoryPolicy[]
FACULTATIF
4 Kategorien
providers
ProviderQuota[]
FACULTATIF
6 Provider-Gruppen
{
"enabled": true,
"warmingEnabled": true,
"startAtWarmingDay": 1,
"maxDeferHours": 48,
"defaultCategory": "transactional",
"preset": "warming_28d"
}
# 28-Tage IP-Warming aktivieren:
nextxch-cli update TransactionalSend --set preset=warming_28d
# Direkt auf Warming-Tag 14 vorspringen:
nextxch-cli update TransactionalSend --set startAtWarmingDay=14
curl -fsS -X PATCH "https://mail.firma.de/api/admin/cli/objects/TransactionalSend/singleton" \
-H "Authorization: Bearer smk_..." \
-H "Content-Type: application/json" \
-d '{"preset":"warming_28d","enabled":true}'
await http.PatchAsJsonAsync(
"/api/admin/cli/objects/TransactionalSend/singleton",
new { preset = "warming_28d", enabled = true });
ReputationShield (Singleton)
Clé : singleton
RBAC : TenantAdmin+
Protection optionnelle de la réputation sortante : liste de suppression automatique des rebonds/plaintes, désabonnement en un clic RFC 8058, disjoncteur de rebonds, temporisation adaptative 421 vis-à-vis des FAI et webhooks HMAC-SHA256.
/api/admin/cli/objects/ReputationShield/singleton
Récupère la configuration actuelle de Reputation Shield
/api/admin/cli/objects/ReputationShield/singleton
Met à jour les indicateurs de protection ou applique un préréglage
preset
string
ÉCRITURE SEULE (SECRET)
"off""recommended""strict_bulk"enableSuppressionPreCheck
boolean
FACULTATIF
false
enforceSuppressionOnSmtpRelay
boolean
FACULTATIF
false
allSuppressedBehavior
string
FACULTATIF
reject_422
"reject_422""accept_noop"autoSuppressHardBounces
boolean
FACULTATIF
false
hardBounceSuppressionDays
integer
FACULTATIF
180
autoSuppressConsecutiveSoftBounces
boolean
FACULTATIF
false
softBounceEscalationThreshold
integer
FACULTATIF
5
autoSuppressFblComplaints
boolean
FACULTATIF
false
enableOneClickUnsubscribe
boolean
FACULTATIF
false
oneClickUnsubscribeCategories
string[]
FACULTATIF
["marketing","notification"]
enableBounceCircuitBreaker
boolean
FACULTATIF
false
maxHardBouncePercent
number
FACULTATIF
5.0
maxComplaintPercent
number
FACULTATIF
0.1
allowCriticalWhenTripped
boolean
FACULTATIF
true
enableAdaptiveIspBackoff
boolean
FACULTATIF
false
ispCooldownMinutes
integer
FACULTATIF
15
webhookEnabled
boolean
FACULTATIF
false
webhookUrl
string
FACULTATIF
webhookSecret
string
ÉCRITURE SEULE (SECRET)
{
"preset": "recommended",
"enableSuppressionPreCheck": true,
"autoSuppressHardBounces": true,
"hardBounceSuppressionDays": 180,
"enableOneClickUnsubscribe": true,
"oneClickUnsubscribeCategories": ["marketing", "notification"],
"enableBounceCircuitBreaker": true,
"maxHardBouncePercent": 5.0,
"maxComplaintPercent": 0.1,
"allowCriticalWhenTripped": true,
"enableAdaptiveIspBackoff": true,
"webhookEnabled": true,
"webhookUrl": "https://erp.firma.de/webhooks/nextxch"
}
# Empfohlenen Reputationsschutz aktivieren:
nextxch-cli update ReputationShield --set preset=recommended
# Webhook-Ziel konfigurieren:
nextxch-cli update ReputationShield \
--set webhookEnabled=true \
--set webhookUrl=https://erp.firma.de/webhooks/nextxch \
--set webhookSecret=whsec_9f8e7d6c5b4a
curl -fsS -X PATCH "https://mail.firma.de/api/admin/cli/objects/ReputationShield/singleton" \
-H "Authorization: Bearer smk_..." \
-H "Content-Type: application/json" \
-d '{"preset":"recommended"}'
await http.PatchAsJsonAsync(
"/api/admin/cli/objects/ReputationShield/singleton",
new { preset = "recommended" });
SpamGuard (Singleton)
Clé : singleton
RBAC : ServerAdmin+
Défense entrante multicouche : vérification SPF/DKIM/DMARC/ARC, Smart Greylisting (/24 IPv4 & /64 IPv6), classifieur ML en ligne (FTRL-Proximal), zones DNSBL, listes d'autorisation/de blocage et analyse TCP ClamAV.
/api/admin/cli/objects/SpamGuard/singleton
Récupère les seuils SpamGuard & les compteurs d'apprentissage
/api/admin/cli/objects/SpamGuard/singleton
Met à jour sur place les scores, DNSBL, listes d'autorisation ou ClamAV
enableEmailAuthChecks
boolean
FACULTATIF
true
enableGreylisting
boolean
FACULTATIF
true
greylistRetryDelaySeconds
integer
FACULTATIF
240
junkScoreThreshold
number
FACULTATIF
4.5
rejectScoreThreshold
number
FACULTATIF
9.0
tagSubjectOnJunk
boolean
FACULTATIF
false
subjectTagPrefix
string
FACULTATIF
"[SPAM] "
enableStructuralHeuristics
boolean
FACULTATIF
true
dnsblZones
string[]
FACULTATIF
["bl.spamcop.net","ix.dnsbl.manitu.net"]
dnsblHitScore
number
FACULTATIF
3.5
allowedSendersOrDomains
string[]
FACULTATIF
[]
blockedSendersOrDomains
string[]
FACULTATIF
[]
clamAvEnabled
boolean
FACULTATIF
false
clamAvHost
string
FACULTATIF
"127.0.0.1"
clamAvPort
integer
FACULTATIF
3310
{
"enableEmailAuthChecks": true,
"enableGreylisting": true,
"greylistRetryDelaySeconds": 240,
"junkScoreThreshold": 4.5,
"rejectScoreThreshold": 9.0,
"enableStructuralHeuristics": true,
"dnsblZones": ["bl.spamcop.net", "ix.dnsbl.manitu.net"],
"dnsblHitScore": 3.5,
"allowedSendersOrDomains": ["datev.de", "partner-spedition.de"],
"blockedSendersOrDomains": [],
"clamAvEnabled": false,
"clamAvHost": "127.0.0.1",
"clamAvPort": 3310
}
# Partner-Domains auf die Allowlist setzen:
nextxch-cli update SpamGuard \
--set allowedSendersOrDomains=datev.de,partner-spedition.de
# Schwellenwerte anpassen:
nextxch-cli update SpamGuard --set junkScoreThreshold=4.5 --set rejectScoreThreshold=9.0
curl -fsS -X PATCH "https://mail.firma.de/api/admin/cli/objects/SpamGuard/singleton" \
-H "Authorization: Bearer smk_..." \
-H "Content-Type: application/json" \
-d '{"junkScoreThreshold":4.5,"rejectScoreThreshold":9.0,"allowedSendersOrDomains":["datev.de"]}'
await http.PatchAsJsonAsync(
"/api/admin/cli/objects/SpamGuard/singleton",
new { junkScoreThreshold = 4.5, rejectScoreThreshold = 9.0 });
SmtpQueue (Singleton)
Clé : singleton
RBAC : ServerAdmin+
Contrôle la file d'attente de remise MX sortante, la concurrence des workers, les intervalles de nouvelle tentative, la limitation de débit par FAI, la validation TLS sortante, le smart host global et les limites ESMTP entrantes.
/api/admin/cli/objects/SmtpQueue/singleton
Récupère tous les paramètres de file d'attente, TLS et ESMTP
/api/admin/cli/objects/SmtpQueue/singleton
Met à jour les workers de la file d'attente, le calendrier de nouvelles tentatives ou les limites ESMTP en 0 ms
outboundQueuePaused
boolean
FACULTATIF
false
outboundWorkerConcurrency
integer
FACULTATIF
8
maxDeliveryAttempts
integer
FACULTATIF
10
retryScheduleMinutes
integer[]
FACULTATIF
[5,15,60,240,720]
maxConcurrentConnectionsPerMxDomain
integer
FACULTATIF
4
strictThrottleDomains
string[]
FACULTATIF
["t-online.de","gmx.de","web.de","yahoo.com"]
strictThrottleMaxConcurrency
integer
FACULTATIF
2
outboundConnectTimeoutSeconds
integer
FACULTATIF
30
outboundBindAddress
string
FACULTATIF
"" (Auto)
outboundUseStartTls
boolean
FACULTATIF
true
requireOutboundTls
boolean
FACULTATIF
false
outboundTlsCertValidation
string
FACULTATIF
Opportunistic
"Opportunistic""IgnoreErrors""Strict"outboundSmartHost
string
FACULTATIF
""
outboundSmartPort
integer
FACULTATIF
587
maxMessageSizeMb
long
FACULTATIF
50
maxRecipientsPerTransaction
integer
FACULTATIF
100
maxConnectionsPerIp
integer
FACULTATIF
20
tarpitDelayMs
integer
FACULTATIF
1500
requireTlsForAuth
boolean
FACULTATIF
true
{
"outboundQueuePaused": false,
"outboundWorkerConcurrency": 8,
"maxDeliveryAttempts": 10,
"retryScheduleMinutes": [5, 15, 60, 240, 720],
"maxConcurrentConnectionsPerMxDomain": 4,
"strictThrottleDomains": ["t-online.de", "gmx.de", "web.de", "yahoo.com"],
"strictThrottleMaxConcurrency": 2,
"outboundUseStartTls": true,
"requireOutboundTls": false,
"outboundTlsCertValidation": "Opportunistic",
"maxMessageSizeMb": 50,
"maxRecipientsPerTransaction": 100,
"tarpitDelayMs": 1500,
"requireTlsForAuth": true
}
# Outbound-TLS auf Opportunistic (RFC 7435) setzen & MaxMessageSize auf 75 MiB erhöhen:
nextxch-cli update SmtpQueue \
--set outboundTlsCertValidation=Opportunistic \
--set maxMessageSizeMb=75
curl -fsS -X PATCH "https://mail.firma.de/api/admin/cli/objects/SmtpQueue/singleton" \
-H "Authorization: Bearer smk_..." \
-H "Content-Type: application/json" \
-d '{"outboundTlsCertValidation":"Opportunistic","maxMessageSizeMb":75}'
await http.PatchAsJsonAsync(
"/api/admin/cli/objects/SmtpQueue/singleton",
new { outboundTlsCertValidation = "Opportunistic", maxMessageSizeMb = 75 });
TransportRules & Server (Singletons)
Clé : singleton
RBAC : ServerAdmin+
Clause de non-responsabilité juridique à l'échelle de l'organisation (insérée avant la signature DKIM), script Sieve entrant global, seuils d'auto-ban Fail2Ban et ServerHostName canonique.
/api/admin/cli/objects/TransportRules/singleton
Récupère les paramètres de clause de non-responsabilité, de Sieve global et de bannissement automatique
/api/admin/cli/objects/TransportRules/singleton
Met à jour les règles de transport sur place
/api/admin/cli/objects/Server/singleton
Récupère le ServerHostName, le moteur de stockage, la profondeur de la file d'attente et l'état de la licence
/api/admin/cli/objects/Server/singleton
Met à jour le ServerHostName canonique en 0 ms
outboundDisclaimerEnabled
boolean
FACULTATIF
false
outboundDisclaimerExternalOnly
boolean
FACULTATIF
true
outboundDisclaimerText
string
FACULTATIF
""
outboundDisclaimerHtml
string
FACULTATIF
""
inboundSystemSieve
string
FACULTATIF
""
autoBanThreshold
integer
FACULTATIF
8
autoBanDurationMinutes
integer
FACULTATIF
30
serverHostName
string
FACULTATIF
mail.<domain>
storageProvider
string
LECTURE SEULE
Sqlite | SqlServer | Postgres
activeQueueCount
integer
LECTURE SEULE
0
licenseState
string
LECTURE SEULE
EnterpriseActive
{
"outboundDisclaimerEnabled": true,
"outboundDisclaimerExternalOnly": true,
"outboundDisclaimerText": "-- \nMuster Logistik GmbH · Industriestraße 18 · 70565 Stuttgart · HRB 774819",
"outboundDisclaimerHtml": "<p style='font-size:11px;color:#64748b'><strong>Muster Logistik GmbH</strong> · 70565 Stuttgart · HRB 774819</p>",
"inboundSystemSieve": "require [\"fileinto\"];\nif header :contains \"X-Spam-Flag\" \"YES\" { fileinto \"Junk\"; }",
"autoBanThreshold": 8,
"autoBanDurationMinutes": 30
}
# Pflicht-Impressum & Auto-Ban aktualisieren:
nextxch-cli update TransportRules \
--set outboundDisclaimerEnabled=true \
--set autoBanThreshold=8
# Kanonischen Server-Hostnamen abfragen oder setzen:
nextxch-cli get Server
nextxch-cli update Server --set serverHostName=mail.muster-logistik.de
curl -fsS -X GET "https://mail.firma.de/api/admin/cli/objects/Server/singleton" \
-H "Authorization: Bearer smk_..."
var status = await http.GetFromJsonAsync<JsonElement>("/api/admin/cli/objects/Server/singleton");
Console.WriteLine($"Host: {status.GetProperty("serverHostName")}, Queue: {status.GetProperty("activeQueueCount")}");