Aller au contenu
Nouveau : les packs. Hébergement, sécurité et newsletter réunis, jusqu'à 48 € d'économie par mois.
napesheapsecure
Inclus dès l'offre Sécurité Pro

API napesheapsecure

Une API REST en JSON pour lancer des analyses, lire les rapports et recevoir les alertes. Idéale pour l'intégration continue, les tableaux de bord internes et les agences qui gèrent de nombreux sites.

Démarrer

Adresse de base : https://37-27-203-220.sslip.io/api/v1. Créez une clé dans votre tableau de bord, rubrique API et webhooks.

curl https://37-27-203-220.sslip.io/api/v1/sites \
  -H "Authorization: Bearer nss_live_votre_cle"

Authentification

Chaque requête porte l'en-tête Authorization: Bearer <clé>. Les clés commencent par nss_live_. Nous ne conservons que leur empreinte : une clé perdue ne peut pas être réaffichée, seulement révoquée et remplacée.

Quotas et erreurs

  • Offre pro : 2 000 appels par jour.
  • Offre business : 10 000 appels par jour.
  • Offre agence : 50 000 appels par jour.

Les erreurs suivent toujours le même format, avec un code HTTP explicite (400, 401, 403, 404, 429).

{
  "error": {
    "code": "quota_exceeded",
    "message": "Quota quotidien atteint (2000 appels). Réessayez demain ou passez à l'offre Business."
  }
}
GET/sites

Lister vos sites

Renvoie les sites de votre organisation avec leur dernière note.

Réponse

{
  "data": [
    {
      "id": "0b8f…",
      "url": "https://boutique-lumen.example/",
      "hostname": "boutique-lumen.example",
      "verified": true,
      "grade": "B",
      "score": 81,
      "last_scan_at": "2026-09-27T12:30:00Z"
    }
  ]
}
POST/sites

Ajouter un site

Ajoute un site à surveiller. La réponse contient le jeton de vérification du domaine.

Corps de la requête

{ "url": "boutique-lumen.example", "label": "Boutique Lumen" }

Réponse

{
  "data": {
    "id": "0b8f…",
    "hostname": "boutique-lumen.example",
    "verification": {
      "dns_record": "_napesheapsecure.boutique-lumen.example",
      "dns_value": "napesheapsecure-verification=4f1c…",
      "file_url": "https://boutique-lumen.example/.well-known/napesheapsecure-verification.txt",
      "file_content": "4f1c…"
    }
  }
}
POST/scans

Lancer une analyse

Analyse un site de votre organisation. Le mode « full » (fichiers sensibles, ports, contrôles avancés) exige un domaine vérifié. L'analyse est synchrone : la réponse arrive en quelques secondes.

Corps de la requête

{ "site_id": "0b8f…", "mode": "full" }

Réponse

{
  "data": {
    "id": "scn_…",
    "status": "completed",
    "grade": "B",
    "score": 81,
    "counts": { "critical": 0, "high": 1, "medium": 2, "low": 3, "info": 1, "pass": 24 },
    "route": [{ "finding_id": "email.dmarc.none", "grade_after": "A" }],
    "report_url": "https://37-27-203-220.sslip.io/rapport/scn_…"
  }
}
GET/scans/{id}

Lire un rapport complet

Renvoie le rapport complet : tous les constats, leurs preuves et les corrections recommandées.

Réponse

{
  "data": {
    "id": "scn_…",
    "grade": "B",
    "findings": [
      {
        "id": "email.dmarc.none",
        "severity": "medium",
        "title": "DMARC en mode observation seulement",
        "evidence": "v=DMARC1; p=none",
        "points": 6
      }
    ]
  }
}
GET/alerts

Lister les alertes

Les 100 dernières alertes de l'organisation, les plus récentes d'abord.

Réponse

{
  "data": [
    {
      "id": "…",
      "kind": "cert_expiring",
      "severity": "high",
      "title": "Le certificat expire dans 7 jours",
      "site": "boutique-lumen.example",
      "created_at": "2026-09-27T08:00:00Z"
    }
  ]
}

Webhooks

Déclarez une adresse dans votre tableau de bord : nous y envoyons une requête POST à chaque événement. Événements disponibles : scan.completed, alert.created, site.down, site.up.

Chaque requête est signée : l'en-tête X-Napesheapsecure-Signature contient un horodatage t et une signature v1, HMAC SHA-256 de `${t}.${corps}` avec votre secret de webhook. Refusez les requêtes de plus de 5 minutes.

import crypto from "node:crypto";

export function verifierSignature(corps, entete, secret) {
  const { t, v1 } = Object.fromEntries(entete.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const attendu = crypto.createHmac("sha256", secret).update(`${t}.${corps}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(attendu), Buffer.from(v1));
}