{
  "openapi": "3.0.0",
  "info": {
    "title": "Proxym REST API",
    "description": "API REST publique pour la gestion et la supervision des routeurs proxys 5G dédiés Proxym. Permet de vérifier le statut en temps réel des proxys (IP active, opérateur mobile, ping, ville) et de forcer des rotations d'IP à la demande par reconnexion matérielle.",
    "version": "1.0.0",
    "contact": {
      "name": "Proxym Support",
      "email": "hello@proxym.io",
      "url": "https://proxym.io"
    }
  },
  "servers": [
    {
      "url": "https://proxym.io",
      "description": "Serveur de Production"
    }
  ],
  "externalDocs": {
    "description": "Documentation complète de l'intégration et de l'API Proxym",
    "url": "https://proxym.io/docs"
  },
  "paths": {
    "/api/proxies/{assignmentId}/status": {
      "get": {
        "summary": "Statut du proxy en temps réel",
        "description": "Effectue un test de connexion actif via le socket proxy (SOCKS5/HTTP) pour déterminer l'IP WAN active du routeur Teltonika, l'opérateur mobile français actuel (Orange, SFR, Bouygues, Free), le ping de latence et la localisation géographique (ville).",
        "parameters": [
          {
            "name": "assignmentId",
            "in": "path",
            "required": true,
            "description": "L'identifiant unique UUID de l'attribution (assignment) de votre proxy.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Statut récupéré avec succès",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "online": {
                      "type": "boolean",
                      "description": "Indique si le tunnel proxy et le matériel Teltonika sont opérationnels et joignables.",
                      "example": true
                    },
                    "ip": {
                      "type": "string",
                      "description": "L'IP mobile CGNAT active actuelle (ou '—' si hors ligne).",
                      "example": "90.84.14.112"
                    },
                    "operator": {
                      "type": "string",
                      "description": "L'opérateur du réseau mobile français détecté.",
                      "enum": [
                        "Orange France 5G",
                        "SFR 5G",
                        "Bouygues Telecom 5G",
                        "Free Mobile 5G",
                        "Webbing 5G",
                        "En attente de connexion"
                      ],
                      "example": "Orange France 5G"
                    },
                    "ping": {
                      "type": "integer",
                      "description": "Temps de réponse de latence réseau en millisecondes.",
                      "example": 24
                    },
                    "city": {
                      "type": "string",
                      "description": "Ville de sortie de l'IP CGNAT.",
                      "example": "Paris"
                    },
                    "unreachable": {
                      "type": "boolean",
                      "description": "Présent et défini sur 'true' si le routeur est actif mais temporairement injoignable via le proxy tunnel.",
                      "example": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide ou aucun modem physique assigné.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Invalid assignment ID"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Non authentifié. Session utilisateur manquante ou expirée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Accès refusé. L'attribution du proxy ne vous appartient pas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Forbidden"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "L'attribution (assignment) spécifiée n'existe pas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Assignment not found"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erreur serveur interne lors de la vérification.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Internal server error"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/proxies/{assignmentId}/rotate": {
      "post": {
        "summary": "Forcer la rotation d'IP",
        "description": "Déclenche une interruption physique de l'interface mobile du routeur Teltonika RUTX pour forcer une déconnexion et reconnexion au réseau 5G de l'opérateur (CGNAT), ce qui attribue instantanément une nouvelle IP. Cette opération est limitée à 1 rotation toutes les 120 secondes pour des raisons de stabilité matérielle.",
        "parameters": [
          {
            "name": "assignmentId",
            "in": "path",
            "required": true,
            "description": "L'identifiant unique UUID de l'attribution (assignment) de votre proxy.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rotation lancée avec succès",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "IP rotated successfully. It may take up to 10 seconds to stabilize."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "ID d'attribution invalide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Invalid assignment ID"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Non authentifié.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Unauthorized"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Accès interdit (propriétaire incorrect ou le proxy est configuré en IP statique non rotative).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "La rotation d'IP est désactivée pour ce routeur (IP Statique)."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Attribution introuvable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Assignment not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de taux dépassée. Vous devez attendre 120 secondes entre chaque rotation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Rate limit exceeded. Please wait 120 seconds between rotations."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erreur lors de la communication avec le routeur ou de l'enregistrement en base.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Internal server error"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/contact": {
      "post": {
        "summary": "Formulaire de contact support",
        "description": "Envoie un e-mail au support Proxym à l'aide de l'API Resend. Permet aux clients ou visiteurs de soumettre des demandes techniques ou commerciales.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "email",
                  "message"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nom complet de l'expéditeur.",
                    "example": "Jean Dupont"
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Adresse email de contact.",
                    "example": "jean.dupont@gmail.com"
                  },
                  "company": {
                    "type": "string",
                    "description": "Nom de l'entreprise (optionnel).",
                    "example": "Acme Corp"
                  },
                  "message": {
                    "type": "string",
                    "description": "Le message envoyé au support.",
                    "example": "Bonjour, je souhaiterais commander 5 ports dédiés supplémentaires..."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message envoyé avec succès",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "description": "Métadonnées de livraison de l'email Resend (si disponible)."
                    },
                    "simulated": {
                      "type": "boolean",
                      "description": "Indique si l'envoi a été simulé en local (lorsque la clé API Resend est absente).",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Champs obligatoires manquants ou erreur Resend.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Missing required fields"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erreur serveur interne.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Internal Server Error"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
