- Updated environment configuration to unify frontend for mail and drive under a single service. - Revised README to reflect changes in frontend setup and routing for the unified application. - Introduced new API documentation endpoints for better accessibility of API specifications. - Enhanced drive and mail services with improved handling of file uploads and metadata enrichment. - Implemented new API token management features, including creation, listing, and revocation of tokens. - Added tests for new functionalities in drive and mail services to ensure reliability and correctness.
553 lines
15 KiB
YAML
553 lines
15 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Ulti Suite API
|
|
version: 1.0.0
|
|
description: |
|
|
API REST Ultimail, UltiDrive et Contacts exposée par **ultid** sous `/api/v1`.
|
|
|
|
## Authentification
|
|
|
|
Deux modes :
|
|
|
|
| Mode | Header | Usage |
|
|
|------|--------|-------|
|
|
| **Session utilisateur** | `Authorization: Bearer <jwt_oidc>` | Interface web, apps avec login OIDC (Authentik) |
|
|
| **Token API** | `Authorization: Bearer ulti_<secret>` | Agents IA, scripts, intégrations programmatiques |
|
|
|
|
Les tokens API portent des permissions **fine-grained** (lecture/écriture par ressource) et des **scopes** optionnels (comptes mail, dossiers Drive).
|
|
|
|
## Permissions tokens API
|
|
|
|
Ressources principales :
|
|
|
|
- **Mail** : `mail.mailboxes`, `mail.labels`, `mail.messages`, `mail.search`, `mail.send`, `mail.attachments`, `mail.settings`, `mail.identities`, `mail.automation`
|
|
- **Drive** : `drive.folders`, `drive.files`, `drive.thumbnails`, `drive.download`, `drive.share`, `drive.upload`, `drive.rename`, `drive.move`, `drive.copy`
|
|
- **Contacts** : `contacts.read`, `contacts.search`, `contacts.write`, `contacts.delete`, `contacts.labels`
|
|
- **Automatisations** : `automation.rules`, `automation.webhooks`, `automation.llm`, `automation.search`, `automation.api_tokens` (super admin)
|
|
|
|
Chaque ressource accepte `read` et/ou `write` selon le cas.
|
|
|
|
## Scopes
|
|
|
|
- **mail_scope** : `{ "all_accounts": true }` ou `{ "all_accounts": false, "account_ids": ["uuid", ...] }`
|
|
- **drive_scope** : `{ "all_folders": true }` ou `{ "all_folders": false, "folder_paths": ["/Projects", ...] }`
|
|
|
|
servers:
|
|
- url: /api/v1
|
|
description: API ultid (proxifiée par nginx)
|
|
|
|
tags:
|
|
- name: Tokens API
|
|
description: Gestion des jetons programmatiques
|
|
- name: Mail
|
|
description: Messages, boîtes, envoi
|
|
- name: Drive
|
|
description: Fichiers et dossiers Nextcloud
|
|
- name: Contacts
|
|
description: Carnet d'adresses
|
|
- name: Automatisations
|
|
description: Règles, webhooks, fournisseurs
|
|
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT or ulti_token
|
|
description: JWT OIDC (session) ou token API `ulti_…`
|
|
schemas:
|
|
ApiTokenPermissionGrant:
|
|
type: object
|
|
required: [resource, read, write]
|
|
properties:
|
|
resource:
|
|
type: string
|
|
example: mail.messages
|
|
read:
|
|
type: boolean
|
|
write:
|
|
type: boolean
|
|
ApiTokenMailScope:
|
|
type: object
|
|
properties:
|
|
all_accounts:
|
|
type: boolean
|
|
account_ids:
|
|
type: array
|
|
items:
|
|
type: string
|
|
format: uuid
|
|
ApiTokenDriveScope:
|
|
type: object
|
|
properties:
|
|
all_folders:
|
|
type: boolean
|
|
folder_paths:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example: /Projects
|
|
ApiToken:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
token_prefix:
|
|
type: string
|
|
example: ulti_a3f9b2c1
|
|
permissions:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ApiTokenPermissionGrant'
|
|
mail_scope:
|
|
$ref: '#/components/schemas/ApiTokenMailScope'
|
|
drive_scope:
|
|
$ref: '#/components/schemas/ApiTokenDriveScope'
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
last_used_at:
|
|
type: string
|
|
format: date-time
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
ApiTokenCreated:
|
|
allOf:
|
|
- $ref: '#/components/schemas/ApiToken'
|
|
- type: object
|
|
required: [token]
|
|
properties:
|
|
token:
|
|
type: string
|
|
description: Secret complet — affiché une seule fois à la création
|
|
CreateApiTokenRequest:
|
|
type: object
|
|
required: [name, permissions, mail_scope, drive_scope]
|
|
properties:
|
|
name:
|
|
type: string
|
|
permissions:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ApiTokenPermissionGrant'
|
|
mail_scope:
|
|
$ref: '#/components/schemas/ApiTokenMailScope'
|
|
drive_scope:
|
|
$ref: '#/components/schemas/ApiTokenDriveScope'
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
MessageSummary:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
account_id:
|
|
type: string
|
|
format: uuid
|
|
subject:
|
|
type: string
|
|
snippet:
|
|
type: string
|
|
date:
|
|
type: string
|
|
format: date-time
|
|
DriveFile:
|
|
type: object
|
|
properties:
|
|
path:
|
|
type: string
|
|
name:
|
|
type: string
|
|
type:
|
|
type: string
|
|
enum: [file, directory]
|
|
size:
|
|
type: integer
|
|
mime_type:
|
|
type: string
|
|
last_modified:
|
|
type: string
|
|
format: date-time
|
|
Error:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
message:
|
|
type: string
|
|
|
|
security:
|
|
- bearerAuth: []
|
|
|
|
paths:
|
|
/mail/api-tokens:
|
|
get:
|
|
tags: [Tokens API]
|
|
summary: Lister les tokens API
|
|
description: Nécessite une session OIDC ou un token avec `automation.api_tokens` (écriture).
|
|
responses:
|
|
'200':
|
|
description: Liste des tokens actifs (sans secret)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
tokens:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ApiToken'
|
|
post:
|
|
tags: [Tokens API]
|
|
summary: Créer un token API
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateApiTokenRequest'
|
|
example:
|
|
name: Agent tri support
|
|
permissions:
|
|
- resource: mail.messages
|
|
read: true
|
|
write: false
|
|
- resource: mail.labels
|
|
read: true
|
|
write: true
|
|
mail_scope:
|
|
all_accounts: false
|
|
account_ids: ["550e8400-e29b-41d4-a716-446655440000"]
|
|
drive_scope:
|
|
all_folders: true
|
|
folder_paths: []
|
|
responses:
|
|
'201':
|
|
description: Token créé — copier le champ `token` immédiatement
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApiTokenCreated'
|
|
|
|
/mail/api-tokens/{tokenID}:
|
|
delete:
|
|
tags: [Tokens API]
|
|
summary: Révoquer un token API
|
|
parameters:
|
|
- name: tokenID
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'204':
|
|
description: Token révoqué
|
|
|
|
/mail/messages:
|
|
get:
|
|
tags: [Mail]
|
|
summary: Lister les messages
|
|
description: |
|
|
Permission requise : `mail.messages` (lecture).
|
|
Scope mail appliqué automatiquement si le token est restreint à certains comptes.
|
|
parameters:
|
|
- name: account_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
- name: folder
|
|
in: query
|
|
schema:
|
|
type: string
|
|
example: inbox
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
- name: page_size
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Page de messages
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
messages:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/MessageSummary'
|
|
|
|
/mail/messages/{messageID}:
|
|
get:
|
|
tags: [Mail]
|
|
summary: Lire un message
|
|
description: Vérifie que le message appartient à un compte autorisé par le token.
|
|
parameters:
|
|
- name: messageID
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Message complet
|
|
'403':
|
|
description: Compte hors scope du token
|
|
|
|
/mail/search:
|
|
get:
|
|
tags: [Mail]
|
|
summary: Rechercher des messages
|
|
description: Permission `mail.search` (lecture).
|
|
parameters:
|
|
- name: q
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: account_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
- name: from
|
|
in: query
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Résultats de recherche
|
|
|
|
/mail/send:
|
|
post:
|
|
tags: [Mail]
|
|
summary: Envoyer un message
|
|
description: Permission `mail.send` (écriture). `account_id` doit être dans le scope.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [account_id, to, subject]
|
|
properties:
|
|
account_id:
|
|
type: string
|
|
format: uuid
|
|
to:
|
|
type: array
|
|
items:
|
|
type: string
|
|
subject:
|
|
type: string
|
|
body_html:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Message envoyé ou mis en file
|
|
|
|
/mail/rules:
|
|
get:
|
|
tags: [Automatisations]
|
|
summary: Lister les règles de tri
|
|
description: Permission `automation.rules` (lecture).
|
|
responses:
|
|
'200':
|
|
description: Règles
|
|
post:
|
|
tags: [Automatisations]
|
|
summary: Créer une règle
|
|
description: Permission `automation.rules` (écriture).
|
|
responses:
|
|
'201':
|
|
description: Règle créée
|
|
|
|
/mail/webhooks:
|
|
get:
|
|
tags: [Automatisations]
|
|
summary: Lister les webhooks
|
|
description: Permission `automation.webhooks` (lecture).
|
|
responses:
|
|
'200':
|
|
description: Webhooks
|
|
post:
|
|
tags: [Automatisations]
|
|
summary: Créer un webhook
|
|
responses:
|
|
'201':
|
|
description: Webhook créé
|
|
|
|
/drive/files/{path}:
|
|
get:
|
|
tags: [Drive]
|
|
summary: Lister un dossier
|
|
description: Permission `drive.folders` ou `drive.files` (lecture). Path relatif au Drive.
|
|
parameters:
|
|
- name: path
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
example: Projects/docs
|
|
responses:
|
|
'200':
|
|
description: Contenu du dossier
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
files:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/DriveFile'
|
|
post:
|
|
tags: [Drive]
|
|
summary: Uploader un fichier
|
|
description: Permission `drive.upload` (écriture). Path = dossier cible.
|
|
parameters:
|
|
- name: path
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
file:
|
|
type: string
|
|
format: binary
|
|
responses:
|
|
'201':
|
|
description: Fichier uploadé
|
|
|
|
/drive/download/{path}:
|
|
get:
|
|
tags: [Drive]
|
|
summary: Télécharger un fichier
|
|
description: Permission `drive.download` (lecture).
|
|
parameters:
|
|
- name: path
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Contenu binaire
|
|
|
|
/drive/preview/{path}:
|
|
get:
|
|
tags: [Drive]
|
|
summary: Miniature / aperçu
|
|
description: Permission `drive.thumbnails` (lecture).
|
|
parameters:
|
|
- name: path
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Image ou flux de prévisualisation
|
|
|
|
/contacts/search:
|
|
get:
|
|
tags: [Contacts]
|
|
summary: Rechercher des contacts
|
|
description: Permission `contacts.search` (lecture).
|
|
parameters:
|
|
- name: q
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Contacts correspondants
|
|
|
|
/contacts/books/{bookID}:
|
|
get:
|
|
tags: [Contacts]
|
|
summary: Lister les contacts d'un carnet
|
|
description: Permission `contacts.read` (lecture).
|
|
parameters:
|
|
- name: bookID
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Contacts du carnet
|
|
post:
|
|
tags: [Contacts]
|
|
summary: Créer un contact
|
|
description: Permission `contacts.write` (écriture).
|
|
responses:
|
|
'201':
|
|
description: Contact créé
|
|
|
|
/contacts/discovery/llm-settings:
|
|
get:
|
|
tags: [Automatisations]
|
|
summary: Lire les fournisseurs LLM
|
|
description: Permission `automation.llm` (lecture).
|
|
responses:
|
|
'200':
|
|
description: Configuration LLM
|
|
put:
|
|
tags: [Automatisations]
|
|
summary: Mettre à jour les fournisseurs LLM
|
|
description: Permission `automation.llm` (écriture).
|
|
responses:
|
|
'200':
|
|
description: Configuration mise à jour
|
|
|
|
/search:
|
|
get:
|
|
tags: [Mail, Drive, Contacts]
|
|
summary: Recherche cross-suite
|
|
description: |
|
|
Vérifie les permissions selon `types` :
|
|
- `mail` → `mail.search`
|
|
- `drive` → `drive.files`
|
|
- `contacts` → `contacts.search`
|
|
parameters:
|
|
- name: q
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- name: types
|
|
in: query
|
|
schema:
|
|
type: string
|
|
example: mail,contacts,drive
|
|
- name: account_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Résultats agrégés
|