Documentation J+SERVICES Guides Référence API

Contrat API — Restitution d’une licence au client final

Destinataire : développeur de l’application mobile Base : https://live.jmoai.net · Enveloppe : { success: boolean, data: …, error?: { code, message } } Authentification : Authorization: Bearer <jwt client>

Le parcours

Le technicien achète la licence et la rattache à son compte pour configurer et provisionner l’équipement — sans titulaire, rien ne se provisionne. Quand le client vient chercher son matériel, le technicien rend la licence, et le client la réclame.

technicien : POST /v1/licenses/:id/release      → la licence devient réclamable
client     : POST /v1/licenses/claim (ou claim-guest) → il en devient titulaire

⚠️ La restitution ne coupe rien. Le matériel remis continue de fonctionner entre la remise et le geste du client — qui peut avoir lieu le lendemain. La bascule du tunnel, du port d’accès distant et du NAS se fait au moment de la réclamation, sans interruption.


1. POST /v1/licenses/:id/release

Rend la licence. Réservé à son titulaire actuel.

// Corps — les deux champs sont facultatifs
{
  "recipient_email": "client@exemple.com", // recommandé, voir ci-dessous
  "reason": "Remise du matériel au client",
}
// 200
{
  "success": true,
  "data": {
    "license_id": "lic_…",
    "license_key": "MK-…",
    "released_to_email": "client@exemple.com",
    "claimable_until": "2026-11-14T…Z",
    "transfers_used": 0,
    "transfers_max": 1,
  },
}

Désignez recipient_email dès que vous le connaissez. Sans lui, la clé fait seule foi : n’importe qui la détenant peut réclamer la licence. C’est acceptable quand la clé est remise en main propre avec le matériel, mais c’est la seule protection.

claimable_until : 90 jours, et jamais avant la fin de validité de la licence — une licence payée ne se ferme pas à la réclamation tant que le droit court.

Erreurs

Code Statut Sens
LICENSE_NOT_FOUND 404 licence inconnue
LICENSE_NOT_HELD 403 vous n’êtes pas le titulaire
LICENSE_NOT_RELEASABLE 400 statut incompatible (expirée, révoquée…)
LICENSE_TRANSFER_LIMIT 400 plafond de transmissions atteint — validation nécessaire
LICENSE_CONCURRENT_UPDATE 400 la licence vient de changer de titulaire

2. POST /v1/licenses/:id/release/cancel

Annule la restitution tant que personne n’a réclamé. Une erreur de destinataire se rattrape sans passer par un administrateur.

// 200
{ "success": true, "data": { "license_id": "lic_…", "released": false } }

3. Côté client — la réclamation ne change pas

POST /v1/licenses/claim et POST /v1/licenses/claim-guest sont inchangés. Ils acceptent désormais, en plus des cas existants, une licence rendue par son titulaire.

Si recipient_email a été désigné, seule cette adresse peut réclamer : toute autre reçoit NOT_FOUND, volontairement indistinct d’une clé inconnue pour ne pas révéler qu’une licence existe.

Un seul code d’erreur est nouveau :

Code Statut Sens
LICENSE_TRANSFER_INCOMPLETE 200* la bascule n’a pas tout déplacé — réessayez la même réclamation

* dans l’enveloppe { success: false }. L’opération est idempotente : rejouer la réclamation la termine. Ne demandez pas au client de recommencer la restitution.


4. Ce que la bascule préserve

5. Limite de transmission

Une licence se transmet une fois par défaut (transfers_max). Au-delà, une validation est nécessaire : c’est ce qui évite qu’une licence devienne un objet qui se revend hors des canaux prévus. transfers_used vous permet de le montrer avant que l’utilisateur agisse.