Droits
read — lecture ; read write — lecture et gestion. Les clients API sont gérés par un utilisateur connecté. Le rôle facturation voit les factures et l’abonnement, mais pas les employés ni les réseaux.
Gérez les entreprises, les membres, l’accès VPN et les routes via la même API que celle utilisée par l’espace entreprise.
Première version : 169 méthodes du contrat actuel — et non 169 exigences réalisées sur 191. Le brouillon utilise d’autres chemins et processus. Matrice complète de la première version : SSO/SCIM, transfert de propriété, déploiement de micrologiciel sur les routeurs, export de configurations et mentions légales des factures sont exclus. Les notification-channels ne sont qu’un inventaire hérité : leur contrat et la livraison email/webhook/in_app sont exclus de la première version. Sept types d’alertes sont disponibles dans la supervision, l’audit et l’API ; la livraison via l’API webhooks signée distincte reste dans le périmètre. Les routeurs et les ressources ne sont pour l’instant qu’un inventaire ; billing-profile ne fait que stocker des métadonnées, sans lien avec les factures.
Chemin de base : https://meduzacore.com/__api/api/business/v1. L’interface utilise la session utilisateur en cours. Pour l’automatisation, créez un client API dans l’espace entreprise et conservez le secret au moment de sa délivrance.
curl -X POST https://meduzacore.com/__api/api/business/v1/oauth/token \ -d grant_type=client_credentials \ -d client_id=YOUR_CLIENT_ID \ -d client_secret=YOUR_SECRET curl https://meduzacore.com/__api/api/business/v1/organizations/ORGANIZATION_ID/members \ -H "Authorization: Bearer TOKEN"
Transmettez le jeton obtenu dans Authorization: Bearer TOKEN. Le jeton est valable une heure et uniquement dans l’entreprise qui a émis le client. L’accès est révoqué lorsque le client est désactivé ou que l’administrateur qui l’a créé perd ses droits.
read — lecture ; read write — lecture et gestion. Les clients API sont gérés par un utilisateur connecté. Le rôle facturation voit les factures et l’abonnement, mais pas les employés ni les réseaux.
Pour les modifications, utilisez Idempotency-Key. Pour éditer, envoyez If-Match: "3" avec la version actuelle de l’objet. En cas de conflit 412, relisez l’objet.
POST /organizations depuis une session utilisateur.subscription/quotes : nombre de VPN, période et opération purchase, renewal ou upgrade.quote_id et payment_method: stripe_card à subscription/checkout.invoices jusqu’à l’apparition de payment_url ; payez via ce lien.pricing_id issu de catalog/vpn-locations et un Idempotency-Key obligatoire.Un forfait commence à 5 VPN. Prix de base par VPN : $5.99 par mois ou $54.99 par an. Remise sur le forfait : 5–9 VPN — 5 %, 10–99 — 10 %, à partir de 100 — 20 %. Le retour du navigateur après le paiement ne donne pas accès sans vérification du paiement.
Le renouvellement conserve la quantité et la période. L’agrandissement du forfait calcule un complément pour la durée restante. Pour supprimer définitivement un serveur, utilisez POST /organizations/{organization_id}/vpns/{id}/retire avec confirm: true et If-Match. La place est libérée après confirmation de la suppression ; le prix de l’abonnement ne change pas. L’attribution à un employé se transmet avec member_id ; sans lui, le VPN est disponible pour l’entreprise selon les attributions d’accès.
Le champ access de PATCH /organizations/{organization_id}/vpns/{id}, avec If-Match, détermine qui peut utiliser un VPN d’entreprise. company l’ouvre à tous les membres de l’entreprise dont le rôle autorise la connexion ; les listes member_ids et group_ids sont vidées. restricted le réserve aux employés listés et aux membres des groupes listés ; des listes vides retirent l’accès à tous. company accompagné de listes non vides est refusé avec 422. Les réponses GET et /me/vpn-grants contiennent toujours data.access, y compris pour les VPN créés avant l’apparition du champ. Une requête sans access mais avec member_ids ou group_ids fait passer le VPN en restricted, comme auparavant. Le VPN dédié d’un employé est toujours restricted. Les changements de mode sont enregistrés dans l’audit sous vpn_access_changed ; lorsque l’accès est restreint, les identifiants des appareils qui l’ont perdu sont révoqués.
curl -X PATCH https://meduzacore.com/__api/api/business/v1/organizations/ORGANIZATION_ID/vpns/VPN_ID \
-H "Authorization: Bearer TOKEN" \
-H 'If-Match: "3"' \
-H "Idempotency-Key: vpn-access-1" \
-H "Content-Type: application/json" \
-d '{"access":"company"}'Un ensemble décrit des sites ou des réseaux, une règle choisit l’action : un VPN précis, en direct ou bloqué. Utilisez les pays et régions de catalog/traffic-presets. En mode first-match, les règles sont vérifiées de haut en bas, 128 au maximum ; le blocage n’est pas disponible pour « Reste du trafic ».
L’enregistrement crée un brouillon. Lancez la validation, puis la publication avec If-Match. Vérifiez policy-deployments : la mise en file d’attente et l’application confirmée par l’appareil sont des états différents. C’est l’application cliente qui se connecte au VPN.
GET /organizations/{id}/roles renvoie les rôles intégrés et personnalisés, les définitions des droits et l’indicateur can_manage. Le propriétaire crée un rôle personnalisé à partir du rôle administrateur, employé ou financier, en ne gardant que les droits nécessaires. L’attribution se fait via PATCH members/{id} : role et custom_role_id. Les changements de droits s’appliquent aussi aux clients API créés par cet utilisateur.
Le rôle autorise des actions dans l’espace. group_ids attribue à l’employé des VPN et un forfait de routage ; l’appartenance à un groupe ne donne aucun droit d’administration. Le rôle propriétaire ne peut pas être copié dans un rôle personnalisé. Un rôle attribué à des employés ne peut pas être supprimé.
Les appareils reçoivent un display_name, un propriétaire et des informations sur le VPN. PATCH devices/{id} ne modifie que le nom, avec vérification If-Match. POST devices/{id}/revocations demande la révocation ; le statut final est confirmé par le nœud. Vos propres appareils sont accessibles via /me/devices. Le champ last_api_ip est l’adresse de transport de l’API, pas celle de la connexion VPN. Le nom et le modèle signalés par l’application ne servent pas à l’autorisation.
GET /organizations/{id}/employee-analytics affiche les connexions observées, les changements d’état et l’historique horaire sur 7 jours. Une mesure manquante n’est pas remplacée par zéro ; le nombre de sessions n’est pas le temps de travail de l’employé.
GET /organizations/{id}/activity renvoie les demandes de connexion enregistrées par le nœud : domaine ou IP demandé, port, protocole, heure, décision, appareil et employé. Filtres : from, to, member_id, action, search ; pages : cursor et limit. Le domaine est transmis par le client dans la demande de connexion, il n’est pas obtenu en déchiffrant le HTTPS.
La collecte est désactivée par défaut. Le propriétaire modifie activity-settings via PATCH avec {"enabled": true} et If-Match. La lecture nécessite activity.read. Lorsque la collecte est active, l’application affiche un avis à l’employé ; la délivrance d’une clé exige une confirmation à jour X-Corporate-Activity-Version après vérification du propriétaire de la clé. Un ancien client ne reçoit pas de clé pour ce mode.
La conservation est limitée à 7 jours et 100 000 événements par entreprise ; le tampon du nœud couvre jusqu’à 24 heures. coverage indique la fraîcheur, les appareils injoignables et les pertes du tampon. Les VPN personnels, le trafic direct de l’appareil, les blocages locaux avant d’atteindre le nœud, les chemins HTTPS, le contenu des requêtes et l’évaluation de la productivité ne sont pas enregistrés. Désactiver la collecte ne restaure pas l’historique manquant et ne supprime pas instantanément les enregistrements déjà collectés : la durée de conservation s’applique.
La réponse du journal contient analysis : répartition par catégorie, employé et heure, principales destinations et le nombre de active_minutes. Les synthèses sont calculées sur tous les événements conservés de la période choisie, quelle que soit la page du journal brut. Le filtre category permet d’accéder aux événements concrets.
Une minute active est une minute unique d’un employé pendant laquelle le nœud a observé une requête. Ce n’est pas une durée de consultation d’un site ni de travail : le trafic en arrière-plan est compté, et les catégories peuvent se chevaucher dans une même minute. Le temps total est calculé séparément et n’est pas la somme des catégories.
Le propriétaire définit jusqu’à 64 règles classification_rules dans les paramètres de journalisation : un domaine et une catégorie. Elles s’appliquent aux sous-domaines et priment sur le référentiel intégré. Les destinations inconnues restent dans une catégorie à part. Les règles actuelles classent toute la période choisie ; la réponse indique la version de la classification.
Sont traitées les destinations des connexions de l’entreprise, et non le contenu HTTPS, les URL complètes ou le trafic personnel. La confirmation de l’avis est enregistrée une seule fois par employé dans l’entreprise ; changer les catégories, les groupes ou le mode de collecte ne demande pas de confirmer à nouveau le même avis. Les indicateurs de couverture incomplète et truncated ne doivent pas être interprétés comme une absence d’activité.
Créez des webhooks avec une URL HTTPS publique sur le port 443 et les événements audit.event, * ou groups.created, members.updated et d’autres changements de ressources. Le secret n’est affiché qu’à la création ou à la rotation.
Meduza-Signature: t=UNIX_SECONDS,v1=HEX_SIGNATURE Meduza-Event-Id: EVENT_ID Meduza-Delivery-Id: DELIVERY_ID HEX_SIGNATURE = HMAC-SHA256(secret, timestamp + "." + RAW_JSON_BODY)
Vérifiez la signature sur les octets bruts du corps, l’âge admissible du timestamp et la répétition de l’event ID. Pendant une rotation, conservez le secret précédent pour les événements déjà en file d’attente. Toute réponse 2xx vaut succès ; les autres réponses sont réessayées à intervalles croissants, jusqu’à huit tentatives. L’historique et la relivraison manuelle sont disponibles via deliveries. Les livraisons réussies et annulées sont conservées jusqu’à 30 jours, 2 000 au maximum par webhook. La file d’attente et les erreurs sont limitées à 1 000 événements ; en cas de débordement, les plus anciens sont supprimés et le compteur dropped_deliveries signale la perte. Dans ce cas, resynchronisez l’état via l’API.
La livraison se fait au moins une fois. En plus des changements faits via l’API, sont envoyés les changements confirmés des factures (invoices.updated), des abonnements (subscriptions.updated), de la disponibilité des VPN (vpns.updated) et les alertes (alerts.created). Une nouvelle interrogation sans changement d’état ne crée pas de nouvel événement. Ce n’est pas un flux de trafic réseau. Les IP privées, les redirections et les appels à des services internes sont interdits.
Chargement du contrat…
Pour les listes d’inventaire, passez limit=1..200, puis cursor depuis next_cursor, en gardant les autres paramètres. Sans limit/cursor, les anciens clients reçoivent la liste complète : les données ne sont jamais tronquées en silence. Sont disponibles status, member_id, user_id, vpn_id, search et created_from/created_to (RFC3339, borne inférieure incluse, borne supérieure exclue). L’accès est vérifié avant le filtrage et sur chaque page. Les paramètres inconnus ou répétés renvoient 422. Les listes du journal d’activité utilisent un contrat distinct. Paramètres de chaque méthode.
L’audit administratif est conservé jusqu’à 90 jours, au maximum les 10 000 derniers événements par entreprise ; les enregistrements d’idempotence expirés sont purgés. Cette purge ne supprime ni les factures ni les abonnements. Les listes d’inventaire renvoient items, total et next_cursor ; la suite apparaît avec un limit/cursor explicite. Sans eux, la réponse complète reste compatible avec les anciens clients. Le journal activity prend en charge séparément un curseur et les filtres documentés. Les secrets ne sont pas répétés dans les réponses issues du cache d’idempotence. La révocation confirmée d’une clé provient du serveur VPN ; la désactivation d’une adhésion interdit immédiatement toute nouvelle délivrance.
La supervision montre les connexions et la charge réelles. L’historique des destinations est disponible via un journal distinct à activer explicitement. Le contenu HTTPS et l’évaluation de la productivité des employés ne font pas partie de ces données. SSO/SCIM et les autres méthodes du projet étendu ne font pas partie de ce contrat implémenté.
Les erreurs de gestion renvoient application/problem+json avec status, detail et request_id. Les erreurs de délivrance du jeton OAuth utilisent le champ error.