Français
Carnet
Les routes sont relatives à <PUBLIC_BASE_URL> ; les corps de requête et de réponse sont en JSON sauf mention contraire. L’authentification, les portées, la pagination et le format des erreurs sont décrits dans les guides de l’API REST.
GET /api/v1/contacts
Lister le carnet
La vue fusionnée du membre : couche partagée et couche personnelle côte à côte, chaque entrée résolue en profil tel qu’un message rédigé l’utiliserait. Filtres kind (adresse ou domaine), layer, q ; résolution du point de vue d’une mailboxId. Paginée par curseur.
Accès — Session de membre ou clé d’API portant contacts:read.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
kind | requête | "contact" | "domain" | non |
q | requête | string | non |
layer | requête | "all" | "shared" | "member" | non |
mailboxId | requête | string | non |
cursor | requête | string | non |
limit | requête | integer | non |
Réponses
200 — Une page d’entrées.
| Champ | Type | Requis |
|---|---|---|
items | object[] | oui |
nextCursor | string | null | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"kind": { "type": "string", "enum": [ "contact", "domain" ] },
"value": { "type": "string", "minLength": 1, "maxLength": 320 },
"shared": {
"anyOf": [
{
"type": "object",
"properties": {
"id": { "type": "string" },
"displayName": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"language": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"status": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"orgNotes": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"updatedAt": { "type": "string" }
},
"required": [
"id",
"displayName",
"language",
"status",
"orgNotes",
"updatedAt"
],
"additionalProperties": false
},
{ "type": "null" }
]
},
"member": {
"anyOf": [
{
"type": "object",
"properties": {
"id": { "type": "string" },
"formality": {
"anyOf": [
{ "type": "string", "enum": [ "tu", "vous" ] },
{ "type": "null" }
]
},
"tone": {
"anyOf": [
{
"type": "string",
"enum": [ "formal", "neutral", "casual" ]
},
{ "type": "null" }
]
},
"language": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"personalNotes": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"updatedAt": { "type": "string" }
},
"required": [
"id",
"formality",
"tone",
"language",
"signatureId",
"personalNotes",
"updatedAt"
],
"additionalProperties": false
},
{ "type": "null" }
]
},
"memberByMailbox": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"formality": {
"anyOf": [
{ "type": "string", "enum": [ "tu", "vous" ] },
{ "type": "null" }
]
},
"tone": {
"anyOf": [
{
"type": "string",
"enum": [ "formal", "neutral", "casual" ]
},
{ "type": "null" }
]
},
"language": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"personalNotes": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"updatedAt": { "type": "string" },
"mailboxId": { "type": "string" }
},
"required": [
"id",
"formality",
"tone",
"language",
"signatureId",
"personalNotes",
"updatedAt",
"mailboxId"
],
"additionalProperties": false
}
},
"resolved": {
"type": "object",
"properties": {
"formality": {
"anyOf": [
{ "type": "string", "enum": [ "tu", "vous" ] },
{ "type": "null" }
]
},
"tone": {
"anyOf": [
{
"type": "string",
"enum": [ "formal", "neutral", "casual" ]
},
{ "type": "null" }
]
},
"language": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"displayName": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureText": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"status": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"notes": { "type": "array", "items": { "type": "string" } }
},
"required": [
"formality",
"tone",
"language",
"displayName",
"signatureText",
"signatureId",
"status",
"notes"
],
"additionalProperties": false
},
"sources": {
"type": "object",
"properties": {
"formality": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"tone": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"language": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"displayName": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"signatureText": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"status": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"notes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
}
}
},
"required": [
"formality",
"tone",
"language",
"displayName",
"signatureText",
"status",
"notes"
],
"additionalProperties": false
}
},
"required": [
"kind",
"value",
"shared",
"member",
"memberByMailbox",
"resolved",
"sources"
],
"additionalProperties": false
}
},
"nextCursor": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "items", "nextCursor" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, contacts.mailbox_not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
DELETE /api/v1/contacts
Retirer une fiche
Retire la fiche kind/value de la couche layer (défaut member). Pour la couche membre, mailboxId vise la fiche de cette boîte ; sans elle, seule la fiche globale part et les fiches par boîte survivent. La couche shared exige le rôle administrateur (403).
Accès — Session de membre ou clé d’API portant contacts:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
kind | requête | "contact" | "domain" | oui |
value | requête | string | oui |
layer | requête | "member" | "shared" | non |
mailboxId | requête | string | non |
Réponses
204 — Retirée.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, auth.forbidden, contacts.invalid_value, contacts.mailbox_not_found, contacts.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
PUT /api/v1/contacts/member
Enregistrer ma fiche pour un contact
Crée ou met à jour la fiche relationnelle du membre (tutoiement, ton, langue, signature, notes) pour une adresse ou un domaine. Avec mailboxId, la fiche est propre à cette boîte et l’emporte sur la globale. Seuls les champs présents sont écrits ; null en efface un. Rend l’entrée fusionnée complète.
Accès — Session de membre ou clé d’API portant contacts:write.
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
kind | "contact" | "domain" | oui |
value | string | oui |
mailboxId | string | non |
formality | "tu" | "vous" | null | non |
tone | "formal" | "neutral" | "casual" | null | non |
language | string | null | non |
signatureId | string | null | non |
personalNotes | string | null | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"kind": { "type": "string", "enum": [ "contact", "domain" ] },
"value": { "type": "string", "minLength": 1, "maxLength": 320 },
"mailboxId": { "type": "string" },
"formality": {
"anyOf": [ { "type": "string", "enum": [ "tu", "vous" ] }, { "type": "null" } ]
},
"tone": {
"anyOf": [
{ "type": "string", "enum": [ "formal", "neutral", "casual" ] },
{ "type": "null" }
]
},
"language": {
"anyOf": [
{ "type": "string", "pattern": "^[a-z]{2}(-[A-Za-z0-9]{2,8})?$" },
{ "type": "null" }
]
},
"signatureId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"personalNotes": { "anyOf": [ { "type": "string", "maxLength": 4000 }, { "type": "null" } ] }
},
"required": [ "kind", "value" ]
}Réponses
200 — L’entrée fusionnée.
| Champ | Type | Requis |
|---|---|---|
entry | object | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"entry": {
"type": "object",
"properties": {
"kind": { "type": "string", "enum": [ "contact", "domain" ] },
"value": { "type": "string", "minLength": 1, "maxLength": 320 },
"shared": {
"anyOf": [
{
"type": "object",
"properties": {
"id": { "type": "string" },
"displayName": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"language": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"status": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"orgNotes": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"updatedAt": { "type": "string" }
},
"required": [
"id",
"displayName",
"language",
"status",
"orgNotes",
"updatedAt"
],
"additionalProperties": false
},
{ "type": "null" }
]
},
"member": {
"anyOf": [
{
"type": "object",
"properties": {
"id": { "type": "string" },
"formality": {
"anyOf": [
{ "type": "string", "enum": [ "tu", "vous" ] },
{ "type": "null" }
]
},
"tone": {
"anyOf": [
{
"type": "string",
"enum": [ "formal", "neutral", "casual" ]
},
{ "type": "null" }
]
},
"language": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"personalNotes": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"updatedAt": { "type": "string" }
},
"required": [
"id",
"formality",
"tone",
"language",
"signatureId",
"personalNotes",
"updatedAt"
],
"additionalProperties": false
},
{ "type": "null" }
]
},
"memberByMailbox": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"formality": {
"anyOf": [
{ "type": "string", "enum": [ "tu", "vous" ] },
{ "type": "null" }
]
},
"tone": {
"anyOf": [
{
"type": "string",
"enum": [ "formal", "neutral", "casual" ]
},
{ "type": "null" }
]
},
"language": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"personalNotes": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"updatedAt": { "type": "string" },
"mailboxId": { "type": "string" }
},
"required": [
"id",
"formality",
"tone",
"language",
"signatureId",
"personalNotes",
"updatedAt",
"mailboxId"
],
"additionalProperties": false
}
},
"resolved": {
"type": "object",
"properties": {
"formality": {
"anyOf": [
{ "type": "string", "enum": [ "tu", "vous" ] },
{ "type": "null" }
]
},
"tone": {
"anyOf": [
{ "type": "string", "enum": [ "formal", "neutral", "casual" ] },
{ "type": "null" }
]
},
"language": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"displayName": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureText": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"status": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"notes": { "type": "array", "items": { "type": "string" } }
},
"required": [
"formality",
"tone",
"language",
"displayName",
"signatureText",
"signatureId",
"status",
"notes"
],
"additionalProperties": false
},
"sources": {
"type": "object",
"properties": {
"formality": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"tone": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"language": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"displayName": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"signatureText": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"status": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"notes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
}
}
},
"required": [
"formality",
"tone",
"language",
"displayName",
"signatureText",
"status",
"notes"
],
"additionalProperties": false
}
},
"required": [
"kind",
"value",
"shared",
"member",
"memberByMailbox",
"resolved",
"sources"
],
"additionalProperties": false
}
},
"required": [ "entry" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, contacts.invalid_value, contacts.mailbox_not_found, contacts.unknown_signature. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
Exemple de requête
json
{
"kind": "contact",
"value": "bob@example.test",
"formality": "tu",
"tone": "casual",
"language": "fr"
}DELETE /api/v1/contacts/member
Retirer ma fiche pour un contact
L’alias historique de DELETE /api/v1/contacts avec layer forcé à member. Même handler, mêmes règles.
Accès — Session de membre ou clé d’API portant contacts:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
kind | requête | "contact" | "domain" | oui |
value | requête | string | oui |
layer | requête | "member" | "shared" | non |
mailboxId | requête | string | non |
Réponses
204 — Retirée.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, contacts.invalid_value, contacts.mailbox_not_found, contacts.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
PUT /api/v1/contacts/shared
Enregistrer la fiche partagée d’un contact
Crée ou met à jour la fiche de l’organisation (nom affiché, langue, statut, notes) pour une adresse ou un domaine. Administrateurs seulement. Rend l’entrée telle que la voit l’administrateur appelant.
Accès — Session de membre ou clé d’API portant admin:write (rôle administrateur requis).
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
kind | "contact" | "domain" | oui |
value | string | oui |
displayName | string | null | non |
language | string | null | non |
status | string | null | non |
orgNotes | string | null | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"kind": { "type": "string", "enum": [ "contact", "domain" ] },
"value": { "type": "string", "minLength": 1, "maxLength": 320 },
"displayName": { "anyOf": [ { "type": "string", "maxLength": 200 }, { "type": "null" } ] },
"language": {
"anyOf": [
{ "type": "string", "pattern": "^[a-z]{2}(-[A-Za-z0-9]{2,8})?$" },
{ "type": "null" }
]
},
"status": { "anyOf": [ { "type": "string", "maxLength": 40 }, { "type": "null" } ] },
"orgNotes": { "anyOf": [ { "type": "string", "maxLength": 4000 }, { "type": "null" } ] }
},
"required": [ "kind", "value" ]
}Réponses
200 — L’entrée fusionnée.
| Champ | Type | Requis |
|---|---|---|
entry | object | oui |
Même schéma que PUT /api/v1/contacts/member.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, contacts.invalid_value. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
DELETE /api/v1/contacts/shared
Retirer la fiche partagée d’un contact
Administrateurs seulement. Les fiches personnelles des membres sont intactes.
Accès — Session de membre ou clé d’API portant admin:write (rôle administrateur requis).
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
kind | requête | "contact" | "domain" | oui |
value | requête | string | oui |
layer | requête | "member" | "shared" | non |
mailboxId | requête | string | non |
Réponses
204 — Retirée.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, contacts.invalid_value, contacts.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
GET /api/v1/contacts/defaults
Lire mes défauts de profil
Ce qu’un message utilise quand aucune fiche ne dit autrement : les défauts du membre, ou ceux d’une de ses boîtes avec mailboxId. Les défauts de l’organisation se lisent ailleurs, par les administrateurs.
Accès — Session de membre ou clé d’API portant contacts:read.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
mailboxId | requête | string | non |
Réponses
200 — Les défauts.
| Champ | Type | Requis |
|---|---|---|
defaults | object | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"defaults": {
"type": "object",
"properties": {
"formality": {
"anyOf": [ { "type": "string", "enum": [ "tu", "vous" ] }, { "type": "null" } ]
},
"tone": {
"anyOf": [
{ "type": "string", "enum": [ "formal", "neutral", "casual" ] },
{ "type": "null" }
]
},
"language": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "formality", "tone", "language", "signatureId" ],
"additionalProperties": false
}
},
"required": [ "defaults" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, contacts.mailbox_not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
PUT /api/v1/contacts/defaults
Modifier mes défauts de profil
Partiel : seuls les champs présents sont écrits, null en efface un. Avec mailboxId, les défauts de cette boîte.
Accès — Session de membre ou clé d’API portant contacts:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
mailboxId | requête | string | non |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
formality | "tu" | "vous" | null | non |
tone | "formal" | "neutral" | "casual" | null | non |
language | string | null | non |
signatureId | string | null | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"formality": {
"anyOf": [ { "type": "string", "enum": [ "tu", "vous" ] }, { "type": "null" } ]
},
"tone": {
"anyOf": [
{ "type": "string", "enum": [ "formal", "neutral", "casual" ] },
{ "type": "null" }
]
},
"language": {
"anyOf": [
{ "type": "string", "pattern": "^[a-z]{2}(-[A-Za-z0-9]{2,8})?$" },
{ "type": "null" }
]
},
"signatureId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
}
}Réponses
200 — Les défauts, mis à jour.
| Champ | Type | Requis |
|---|---|---|
defaults | object | oui |
Même schéma que GET /api/v1/contacts/defaults.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, contacts.mailbox_not_found, contacts.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/contacts/resolve
Résoudre des profils de destinataires
Exactement ce qu’un message rédigé verrait pour chaque adresse : le profil résolu et l’origine de chaque champ. Un POST parce qu’un lot d’adresses n’a rien à faire dans une URL. mailboxId est la boîte d’envoi ; sans elle, les défauts globaux du membre s’appliquent.
Accès — Session de membre ou clé d’API portant contacts:read.
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
emails | string[] | oui |
mailboxId | string | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"emails": {
"minItems": 1,
"maxItems": 100,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 320 }
},
"mailboxId": { "type": "string" }
},
"required": [ "emails" ]
}Réponses
200 — Les profils et leurs sources, par adresse.
| Champ | Type | Requis |
|---|---|---|
profiles | object | oui |
sources | object | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"profiles": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {
"type": "object",
"properties": {
"formality": {
"anyOf": [
{ "type": "string", "enum": [ "tu", "vous" ] },
{ "type": "null" }
]
},
"tone": {
"anyOf": [
{ "type": "string", "enum": [ "formal", "neutral", "casual" ] },
{ "type": "null" }
]
},
"language": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"displayName": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureText": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"signatureId": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"status": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"notes": { "type": "array", "items": { "type": "string" } }
},
"required": [
"formality",
"tone",
"language",
"displayName",
"signatureText",
"signatureId",
"status",
"notes"
],
"additionalProperties": false
}
},
"sources": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {
"type": "object",
"properties": {
"formality": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"tone": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"language": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"displayName": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"signatureText": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"status": {
"anyOf": [
{
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
},
{ "type": "null" }
]
},
"notes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"org_default",
"shared_domain",
"shared_contact",
"member_default",
"member_mailbox_default",
"member_domain",
"member_contact",
"member_mailbox_domain",
"member_mailbox_contact"
]
}
}
},
"required": [
"formality",
"tone",
"language",
"displayName",
"signatureText",
"status",
"notes"
],
"additionalProperties": false
}
}
},
"required": [ "profiles", "sources" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, contacts.mailbox_not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/contacts/import/preview
Prévisualiser un import CSV
Lit le CSV, détecte le séparateur, propose une correspondance de colonnes et rend des lignes d’exemple. Ne change rien. Un POST parce que le fichier est dans le corps.
Accès — Session de membre ou clé d’API portant contacts:read.
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
csv | string | oui |
delimiter | "," | ";" | "\t" | "auto" | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"csv": { "type": "string", "minLength": 1, "maxLength": 2097152 },
"delimiter": { "default": "auto", "type": "string", "enum": [ ",", ";", "\t", "auto" ] }
},
"required": [ "csv" ]
}Réponses
200 — La correspondance proposée et les exemples.
| Champ | Type | Requis |
|---|---|---|
columns | string[] | oui |
sample | string[][] | oui |
suggestedMapping | object | oui |
rowCount | integer | oui |
delimiter | "," | ";" | "\t" | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"columns": { "type": "array", "items": { "type": "string" } },
"sample": {
"type": "array",
"items": { "type": "array", "items": { "type": "string" } }
},
"suggestedMapping": {
"type": "object",
"properties": {
"email": { "type": "string", "minLength": 1 },
"displayName": { "type": "string", "minLength": 1 },
"formality": { "type": "string", "minLength": 1 },
"tone": { "type": "string", "minLength": 1 },
"language": { "type": "string", "minLength": 1 },
"notes": { "type": "string", "minLength": 1 }
},
"additionalProperties": false
},
"rowCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"delimiter": { "type": "string", "enum": [ ",", ";", "\t" ] }
},
"required": [ "columns", "sample", "suggestedMapping", "rowCount", "delimiter" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, contacts.invalid_csv. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/contacts/import
Importer des contacts depuis un CSV
Écrit les lignes dans la couche du membre (éventuellement pour une boîte) ou, pour les administrateurs, dans la couche partagée. Les fiches existantes sont mises à jour ou sautées selon onConflict ; la réponse compte créations, mises à jour et lignes sautées, avec la raison par ligne.
Accès — Session de membre ou clé d’API portant contacts:write.
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
csv | string | oui |
delimiter | "," | ";" | "\t" | "auto" | non |
mapping | object | oui |
layer | "member" | "shared" | oui |
mailboxId | string | non |
onConflict | "skip" | "update" | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"csv": { "type": "string", "minLength": 1, "maxLength": 2097152 },
"delimiter": { "default": "auto", "type": "string", "enum": [ ",", ";", "\t", "auto" ] },
"mapping": {
"type": "object",
"properties": {
"email": { "type": "string", "minLength": 1 },
"displayName": { "type": "string", "minLength": 1 },
"formality": { "type": "string", "minLength": 1 },
"tone": { "type": "string", "minLength": 1 },
"language": { "type": "string", "minLength": 1 },
"notes": { "type": "string", "minLength": 1 }
},
"required": [ "email" ]
},
"layer": { "type": "string", "enum": [ "member", "shared" ] },
"mailboxId": { "type": "string" },
"onConflict": { "type": "string", "enum": [ "skip", "update" ] }
},
"required": [ "csv", "mapping", "layer", "onConflict" ]
}Réponses
200 — Le bilan de l’import.
| Champ | Type | Requis |
|---|---|---|
created | integer | oui |
updated | integer | oui |
skipped | object[] | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"created": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"updated": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"skipped": {
"type": "array",
"items": {
"type": "object",
"properties": {
"row": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"reason": {
"type": "string",
"enum": [ "missing_email", "invalid_email", "duplicate" ]
}
},
"required": [ "row", "reason" ],
"additionalProperties": false
}
}
},
"required": [ "created", "updated", "skipped" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.
Codes d’erreur — request.bad_request, auth.forbidden, contacts.mailbox_not_found, contacts.invalid_csv, contacts.unknown_column. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/contacts/enrichment/runs
Lancer une passe d’enrichissement
Lit le courrier envoyé d’une boîte sur lookbackDays et demande à un modèle de proposer des fiches pour les correspondants les plus fréquents. Enfilé, pas fait : 202 avec l’identifiant du run ; en lire l’état, puis les suggestions.
Accès — Session de membre ou clé d’API portant contacts:write.
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
mailboxId | string | oui |
lookbackDays | integer | non |
maxContacts | integer | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"mailboxId": { "type": "string", "minLength": 1 },
"lookbackDays": { "default": 365, "type": "integer", "minimum": 1, "maximum": 730 },
"maxContacts": { "default": 50, "type": "integer", "minimum": 1, "maximum": 200 }
},
"required": [ "mailboxId" ]
}Réponses
202 — Le run, enfilé.
| Champ | Type | Requis |
|---|---|---|
runId | string | oui |
Schéma JSON
json
{
"type": "object",
"properties": { "runId": { "type": "string" } },
"required": [ "runId" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.
Codes d’erreur — request.bad_request, contacts.mailbox_not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
GET /api/v1/contacts/enrichment/runs/{id}
Lire une passe d’enrichissement
Son état et ses compteurs. Le run d’un autre membre rend 404.
Accès — Session de membre ou clé d’API portant contacts:read.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Réponses
200 — Le run.
| Champ | Type | Requis |
|---|---|---|
id | string | oui |
mailboxId | string | oui |
status | "pending" | "running" | "done" | "failed" | oui |
startedAt | string | null | oui |
finishedAt | string | null | oui |
summary | object | oui |
error | string | null | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"id": { "type": "string" },
"mailboxId": { "type": "string" },
"status": { "type": "string", "enum": [ "pending", "running", "done", "failed" ] },
"startedAt": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"finishedAt": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"summary": {
"type": "object",
"properties": {
"contacts": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"withProposal": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"llmSkipped": { "type": "boolean" }
},
"required": [ "contacts", "withProposal", "llmSkipped" ],
"additionalProperties": false
},
"error": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "id", "mailboxId", "status", "startedAt", "finishedAt", "summary", "error" ],
"additionalProperties": false
}401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — contacts.enrichment_run_not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
GET /api/v1/contacts/suggestions
Lister les suggestions de contacts
Ce que l’enrichissement propose, correspondants les plus fréquents d’abord, paginé par curseur. status vaut pending par défaut. Chaque élément dit si l’adresse a déjà une fiche, pour que l’écran ne propose pas un doublon.
Accès — Session de membre ou clé d’API portant contacts:read.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
mailboxId | requête | string | non |
status | requête | "pending" | "accepted" | "rejected" | non |
cursor | requête | string | non |
limit | requête | integer | non |
Réponses
200 — Une page de suggestions.
| Champ | Type | Requis |
|---|---|---|
items | object[] | oui |
nextCursor | string | null | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"mailboxId": { "type": "string" },
"email": { "type": "string" },
"displayName": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"evidence": {
"type": "object",
"properties": {
"sentCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"receivedCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"lastAt": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "sentCount", "receivedCount", "lastAt" ],
"additionalProperties": false
},
"proposal": {
"anyOf": [
{
"type": "object",
"properties": {
"formality": { "type": "string", "enum": [ "tu", "vous" ] },
"tone": {
"type": "string",
"enum": [ "formal", "neutral", "casual" ]
},
"language": { "type": "string" },
"notes": { "type": "string" }
},
"additionalProperties": false
},
{ "type": "null" }
]
},
"confidence": {
"anyOf": [
{ "type": "number", "minimum": 0, "maximum": 1 },
{ "type": "null" }
]
},
"existing": {
"type": "object",
"properties": {
"layer": {
"anyOf": [
{ "type": "string", "enum": [ "member", "shared" ] },
{ "type": "null" }
]
}
},
"required": [ "layer" ],
"additionalProperties": false
},
"status": { "type": "string", "enum": [ "pending", "accepted", "rejected" ] },
"createdAt": { "type": "string" }
},
"required": [
"id",
"mailboxId",
"email",
"displayName",
"evidence",
"proposal",
"confidence",
"existing",
"status",
"createdAt"
],
"additionalProperties": false
}
},
"nextCursor": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }
},
"required": [ "items", "nextCursor" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request, contacts.mailbox_not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/contacts/suggestions/accept-all
Accepter toutes les suggestions en attente
Chaque suggestion en attente de la boîte devient une fiche, telle que proposée, dans la portée boîte ou membre. Les suggestions tranchées entre-temps sont sautées ; accepted compte celles qui ont réellement basculé.
Accès — Session de membre ou clé d’API portant contacts:write.
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
mailboxId | string | oui |
scope | "mailbox" | "member" | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"mailboxId": { "type": "string", "minLength": 1 },
"scope": { "type": "string", "enum": [ "mailbox", "member" ] }
},
"required": [ "mailboxId", "scope" ]
}Réponses
200 — Combien ont été acceptées.
| Champ | Type | Requis |
|---|---|---|
accepted | integer | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"accepted": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }
},
"required": [ "accepted" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.
Codes d’erreur — request.bad_request, contacts.mailbox_not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/contacts/suggestions/{id}/accept
Accepter une suggestion
La suggestion devient une fiche du membre, avec les valeurs proposées ou les edits donnés, dans la portée mailbox ou member. Tranchée une fois : une suggestion déjà acceptée ou rejetée rend 404.
Accès — Session de membre ou clé d’API portant contacts:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
scope | "mailbox" | "member" | oui |
edits | object | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"scope": { "type": "string", "enum": [ "mailbox", "member" ] },
"edits": {
"type": "object",
"properties": {
"displayName": { "type": "string", "maxLength": 200 },
"formality": { "type": "string", "enum": [ "tu", "vous" ] },
"tone": { "type": "string", "enum": [ "formal", "neutral", "casual" ] },
"language": { "type": "string", "pattern": "^[a-z]{2}(-[A-Za-z0-9]{2,8})?$" },
"notes": { "type": "string", "maxLength": 4000 }
}
}
},
"required": [ "scope" ]
}Réponses
200 — L’entrée fusionnée.
| Champ | Type | Requis |
|---|---|---|
entry | object | oui |
Même schéma que PUT /api/v1/contacts/member.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Cette opération accepte un en-tête Idempotency-Key : rejouer la même requête avec la même clé rend la réponse d’origine au lieu d’agir deux fois. Voir Idempotence.
Codes d’erreur — request.bad_request, contacts.suggestion_not_found, contacts.mailbox_not_found, contacts.invalid_value, contacts.unknown_signature. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
POST /api/v1/contacts/suggestions/{id}/reject
Rejeter une suggestion
L’adresse ne sera plus proposée par les passes suivantes.
Accès — Session de membre ou clé d’API portant contacts:write.
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Réponses
204 — Rejetée.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — contacts.suggestion_not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
GET /api/v1/admin/contacts/defaults
Lire les défauts de rédaction de l’organisation
Tutoiement, ton, langue et signature appliqués quand ni la fiche ni le membre ne disent autrement.
Accès — Session de membre ou clé d’API portant admin:read (rôle administrateur requis).
Réponses
200 — Les défauts.
| Champ | Type | Requis |
|---|---|---|
defaults | object | oui |
Même schéma que GET /api/v1/contacts/defaults.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
PUT /api/v1/admin/contacts/defaults
Régler les défauts de rédaction de l’organisation
Trois états par champ : absent (inchangé), null (effacé), une valeur.
Accès — Session de membre ou clé d’API portant admin:write (rôle administrateur requis).
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
formality | "tu" | "vous" | null | non |
tone | "formal" | "neutral" | "casual" | null | non |
language | string | null | non |
signatureId | string | null | non |
Même schéma que PUT /api/v1/contacts/defaults.
Réponses
200 — Les défauts, après écriture.
| Champ | Type | Requis |
|---|---|---|
defaults | object | oui |
Même schéma que GET /api/v1/contacts/defaults.
400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — request.bad_request. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.