Aller au contenu
Documentation développeurOpérationnellev1 · 2026-09-30

API ForenShield

Branchez l’analyse d’e-mails de ForenShield sur vos scripts, votre SOAR ou votre SIEM : un fichier .eml en entrée, un verdict expliqué et tous les observables en sortie.

par analyse
< 1 s
par analyse
par fichier
10 Mo
par fichier
fichier conservé
0
fichier conservé
langages d’exemple
4
langages d’exemple
URL de basehttps://api.forenshield.com
curl -X POST "https://api.forenshield.com/v1/eml/analyze?include=report" \ -H "Authorization: Bearer $FORENSHIELD_API_KEY" \ -H "Content-Type: message/rfc822" \ --data-binary @suspect.eml

Introduction

L’API est une interface REST : requêtes HTTPS, réponses JSON UTF-8, codes HTTP standard. Elle expose le même moteur que l’analyseur .eml du site, sans passer par le navigateur.

  • Sécurisée par conception

    Clés personnelles hachées (bcrypt), scopes par outil, expiration, révocation immédiate. Jamais de clé dans une URL.

  • Aucun fichier conservé

    L’e-mail est analysé en mémoire puis oublié. Le journal ne garde que l’endpoint, le statut et la durée (90 jours).

  • Contrat stable

    JSON en snake_case, versionné par date. Les ajouts sont rétrocompatibles ; toute rupture passera par /v2.

  • Pensée pour l’automatisation

    Réponses en moins d’une seconde, erreurs typées, en-têtes de quota, identifiant de requête pour le support.

Démarrage rapide

  1. 1

    Créez une clé

    Portail → Compte → Développeur. Choisissez ses scopes et sa durée ; la clé n’est affichée qu’une fois.

  2. 2

    Envoyez un .eml

    POST /v1/eml/analyze avec le fichier brut, un formulaire multipart ou du JSON base64.

  3. 3

    Exploitez le verdict

    Score, signaux, liens, observables défangés : de quoi trier, bloquer ou ouvrir un ticket automatiquement.

Obtenir une clé API
curl -X POST "https://api.forenshield.com/v1/eml/analyze?include=report" \ -H "Authorization: Bearer $FORENSHIELD_API_KEY" \ -H "Content-Type: message/rfc822" \ --data-binary @suspect.eml

Authentification

Chaque requête authentifiée porte votre clé dans l’en-tête Authorization (schéma Bearer) ou X-API-Key. Une clé ressemble à fs_3c9e1a7.4f0b… : le préfixe (7 caractères) l’identifie dans votre portail, le secret (64 caractères) n’est jamais stocké en clair.

  • Stockez la clé dans un coffre-fort de secrets ou une variable d’environnement, jamais dans le code.
  • Une clé par intégration, avec les seuls scopes nécessaires et une expiration.
  • N’appelez pas l’API depuis un navigateur public : la clé y serait visible.
  • Clé exposée ? Révoquez-la depuis le portail : l’effet est immédiat.

Une clé passée dans l’URL (?api_key=…) est refusée (400 api_key_in_url) : les URL finissent dans les journaux.

# Recommandé / recommended curl "https://api.forenshield.com/v1/me" -H "Authorization: Bearer fs_3c9e1a7.4f0b…" # Accepté / also accepted curl "https://api.forenshield.com/v1/me" -H "X-API-Key: fs_3c9e1a7.4f0b…"

Scopes

Un scope donne accès à un outil. Une clé sans le scope requis reçoit 403 insufficient_scope. De nouveaux outils rejoindront l’API avec leur propre scope.

EndpointScopeAuthentificationDescription
GET /v1—AucuneIndex de l’API
GET /v1/openapi.json—AucuneSpécification OpenAPI
GET /v1/me—Toute clé valideClé courante
POST /v1/eml/analyzeeml:analyzeBearerAnalyser un e-mail (.eml)

Limites et quotas

Chaque clé dispose d’une limite par minute et d’un quota journalier (remis à zéro à minuit UTC). Au-delà : 429 avec l’en-tête Retry-After. Besoin de plus ? Contactez-nous.

60

requêtes / minute

1 000

requêtes / jour

En-têteSignification
X-RateLimit-LimitRequêtes autorisées par minute.
X-RateLimit-RemainingRequêtes restantes dans la minute en cours.
X-RateLimit-ResetFin de la fenêtre (timestamp Unix, secondes).
X-Quota-Limit / X-Quota-RemainingQuota du jour et requêtes restantes.
Retry-AfterSecondes à attendre (réponses 429).
X-Request-IdIdentifiant unique, à communiquer au support.
# Les en-têtes indiquent le quota restant et, en cas de 429, le délai à respecter. curl -i "https://api.forenshield.com/v1/me" -H "Authorization: Bearer $FORENSHIELD_API_KEY" # X-RateLimit-Remaining: 59 # X-Quota-Remaining: 998 # Retry-After: 12 (réponse 429 uniquement)

Erreurs

Les erreurs ont toujours la même forme. Testez type (famille stable) et code (cause précise) ; message est lisible, en français si Accept-Language: fr.

CodeHTTPTypeSignification
missing_api_key401authentication_errorClé API manquante. Envoyez-la dans l’en-tête Authorization: Bearer <clé> ou X-API-Key.
invalid_api_key401authentication_errorClé API invalide.
revoked_api_key401authentication_errorCette clé API a été révoquée.
expired_api_key401authentication_errorCette clé API a expiré.
api_key_in_url400invalid_request_errorNe transmettez jamais une clé API dans l’URL : utilisez l’en-tête Authorization. Révoquez cette clé si l’URL a été journalisée.
account_disabled403permission_errorLe compte associé à cette clé est désactivé ou n’a plus accès à l’API.
insufficient_scope403permission_errorCette clé n’a pas le scope requis pour cet endpoint.
rate_limited429rate_limit_errorTrop de requêtes par minute pour cette clé. Réessayez après le délai indiqué par Retry-After.
quota_exceeded429rate_limit_errorQuota journalier de cette clé atteint. Il se réinitialise à minuit UTC.
route_not_found404not_found_errorEndpoint inconnu. Consultez GET /v1 pour la liste des endpoints.
method_not_allowed405invalid_request_errorMéthode HTTP non prise en charge par cet endpoint.
unsupported_media_type415invalid_request_errorType de contenu non pris en charge. Utilisez message/rfc822, application/octet-stream, multipart/form-data ou application/json.
payload_too_large413invalid_request_errorFichier trop volumineux (10 Mo maximum).
empty_body400invalid_request_errorAucun fichier .eml reçu.
invalid_json400invalid_request_errorCorps JSON invalide.
invalid_base64400invalid_request_errorLe champ eml_base64 n’est pas du base64 valide.
invalid_parameter400invalid_request_errorParamètre invalide.
invalid_eml422invalid_request_errorLe fichier n’est pas un e-mail .eml lisible (en-têtes RFC 5322 introuvables).
internal_error500api_errorErreur interne. Réessayez ; si elle persiste, contactez le support avec le request_id.
error
{ "error": { "type": "permission_error", "code": "insufficient_scope", "message": "This key does not have the scope required by this endpoint.", "param": null, "details": { "required_scope": "eml:analyze", "key_scopes": [] }, "doc_url": "https://forenshield.com/developpeurs/api#erreurs", "request_id": "req_4b1e0c77a2d94f6b8e3a9d12" } }

Endpoints

POST/v1/eml/analyzeeml:analyze

Analyser un e-mail (.eml)

Verdict expliqué, authentification SPF/DKIM/DMARC et alignement, cohérence des identités, inventaire des liens, observables défangés, routage Received et pièces jointes (MD5, SHA-1, SHA-256). Le fichier est analysé en mémoire et n’est jamais conservé.

Corps de la requête

Content-TypeDescription
message/rfc822Le fichier .eml brut (recommandé).
multipart/form-dataChamp file (+ champs include, lang).
application/json{ "eml": "…" } (texte) ou { "eml_base64": "…" }, + filename, include, lang.

Paramètres

ParamètreTypeDescription
includestring · query | form | JSONSections optionnelles, séparées par des virgules : headers, body, report.
langfr | enLangue des libellés de signaux et du rapport (défaut : fr).
filenamestringNom du fichier, renvoyé dans file.name.
curl -X POST "https://api.forenshield.com/v1/eml/analyze?include=report" \ -H "Authorization: Bearer $FORENSHIELD_API_KEY" \ -H "Content-Type: message/rfc822" \ --data-binary @suspect.eml

Variante JSON (base64)

curl -X POST "https://api.forenshield.com/v1/eml/analyze" \ -H "Authorization: Bearer $FORENSHIELD_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"eml_base64\": \"$(base64 -w0 suspect.eml)\", \"include\": [\"headers\"], \"lang\": \"en\"}"

Exemple de réponse

200 OK · application/json
{ "id": "req_7f3a91c2d8e64b05a1c9e2f4", "object": "eml.analysis", "api_version": "2026-09-30", "created_at": "2026-09-30T09:12:04.512Z", "lang": "fr", "file": { "name": "demo-hameconnage.eml", "size": 2198, "md5": "66c6044c7b1be88044336e3ad2dcc22e", "sha1": "9124751a51cf0d51eba352560d1e7f5ea90b8110", "sha256": "a92d9083123c1903e233891f5a14b927a5a5768110d913a8d63e1bf76ae1447f" }, "verdict": { "score": 100, "level": "critical", "label": "Très suspect", "signals": [ { "id": "double-ext-0-releve-compte.pdf.exe", "label": "Double extension trompeuse : releve-compte.pdf.exe.", "points": 35, "severity": "danger" }, { "id": "spf-fail", "label": "Échec SPF : l'expéditeur n'est pas autorisé à envoyer depuis ce domaine.", "points": 25, "severity": "danger" }, { "id": "dmarc-fail", "label": "Échec de la politique DMARC du domaine affiché.", "points": 20, "severity": "danger" }, { "id": "display-name", "label": "Le nom affiché contient une autre adresse ([email protected]) que l’expéditeur réel : usurpation probable.", "points": 20, "severity": "danger" } ] }, "message": { "subject": "Urgent : votre compte sera suspendu sous 24 h", "date": "2026-09-26T07:12:00.000Z", "message_id": "<[email protected]>", "mailer": null, "from": { "name": "[email protected]", "address": "[email protected]" }, "reply_to": { "name": null, "address": "[email protected]" }, "return_path": "[email protected]", "to": [ { "name": null, "address": "[email protected]" } ], "cc": [] }, "authentication": { "receiver": "mx.destinataire.example", "arc": false, "spf": { "result": "fail", "domain": "mailer-exemple.test", "aligned": false }, "dkim": { "result": "none", "domain": null, "aligned": false, "signatures": [] }, "dmarc": { "result": "fail", "policy": "reject", "header_from": "banque-exemp1e.com" }, "identities": [ { "role": "from", "address": "[email protected]", "domain": "banque-exemp1e.com", "aligned": true }, { "role": "replyTo", "address": "[email protected]", "domain": "recuperation-compte.test", "aligned": false }, { "role": "returnPath", "address": "[email protected]", "domain": "mailer-exemple.test", "aligned": false }, { "role": "mailfrom", "address": "mailer-exemple.test", "domain": "mailer-exemple.test", "aligned": false }, { "role": "messageId", "address": "[email protected]", "domain": "banque-exemp1e.com", "aligned": true } ] }, "links": [ { "url": "https://banque-exemp1e.com/verification", "url_defanged": "hxxps[://]banque-exemp1e[.]com/verification", "host": "banque-exemp1e.com", "base_domain": "banque-exemp1e.com", "scheme": "https", "sources": [ "href", "text" ], "displayed_texts": [ "https://www.banque-exemple.fr/espace-client" ], "hidden_destination": null, "flags": [ "deceptive" ], "risk": "danger", "occurrences": 2 }, { "url": "https://recuperation-compte.test/collect", "url_defanged": "hxxps[://]recuperation-compte[.]test/collect", "host": "recuperation-compte.test", "base_domain": "recuperation-compte.test", "scheme": "https", "sources": [ "form" ], "displayed_texts": [], "hidden_destination": null, "flags": [ "form", "external" ], "risk": "danger", "occurrences": 1 } ], "observables": { "urls": [ { "value": "https://banque-exemp1e.com/verification", "defanged": "hxxps[://]banque-exemp1e[.]com/verification", "context": [ "href", "text" ], "risk": "danger" }, { "value": "https://recuperation-compte.test/collect", "defanged": "hxxps[://]recuperation-compte[.]test/collect", "context": [ "form" ], "risk": "danger" } ], "domains": [ { "value": "banque-exemp1e.com", "defanged": "banque-exemp1e[.]com", "context": [ "link", "from" ], "risk": "none" }, { "value": "recuperation-compte.test", "defanged": "recuperation-compte[.]test", "context": [ "link", "replyTo" ], "risk": "none" } ], "ips": [ { "value": "198.51.100.23", "defanged": "198[.]51[.]100[.]23", "context": [ "origin" ], "risk": "none" } ], "emails": [ { "value": "[email protected]", "defanged": "alerte[@]banque-exemp1e[.]com", "context": [ "from", "content" ], "risk": "none" }, { "value": "[email protected]", "defanged": "support[@]recuperation-compte[.]test", "context": [ "replyTo", "content" ], "risk": "none" } ], "hashes": [ { "value": "4656fc54d9b6b16f3fca03f6564348f15afea6af886ca04daaac3f080a095d10", "algorithm": "sha256", "file": "releve-compte.pdf.exe", "risk": "danger" }, { "value": "d10d4660e6b37078cac4d083de2496fb0796aa94", "algorithm": "sha1", "file": "releve-compte.pdf.exe", "risk": "danger" } ], "total": 21 }, "routing": { "origin_ip": "198.51.100.23", "hop_count": 2, "total_seconds": null, "anomalies": 0, "hops": [ { "index": 1, "from_host": "192.168.1.20", "from_reverse_dns": null, "ip": "10.0.0.8", "ip_public": false, "by_host": "relay.mailer-exemple.test", "protocol": null, "tls": false, "date": null, "delay_seconds": null, "anomaly": null }, { "index": 2, "from_host": "relay.mailer-exemple.test", "from_reverse_dns": "relay.mailer-exemple.test", "ip": "198.51.100.23", "ip_public": true, "by_host": "mx.destinataire.example", "protocol": "ESMTPS", "tls": true, "date": "2026-09-26T07:12:00.000Z", "delay_seconds": null, "anomaly": null } ] }, "attachments": [ { "filename": "releve-compte.pdf.exe", "content_type": "application/octet-stream", "size": 50, "inline": false, "md5": "c98b22d6321a7f9f894ebed205b78237", "sha1": "d10d4660e6b37078cac4d083de2496fb0796aa94", "sha256": "4656fc54d9b6b16f3fca03f6564348f15afea6af886ca04daaac3f080a095d10", "dangerous": true, "double_extension": true } ] }

Réponse réelle pour l’e-mail de démonstration, tableaux abrégés.

GET/v1/me

Clé courante

Préfixe, nom, scopes, expiration et quotas restants de la clé utilisée.

curl "https://api.forenshield.com/v1/me" \ -H "Authorization: Bearer $FORENSHIELD_API_KEY"
GET/v1/openapi.jsonAucune

Spécification OpenAPI

Document OpenAPI 3.1 à importer dans Postman, Insomnia ou un générateur de client.

curl -o forenshield-openapi.json "https://api.forenshield.com/v1/openapi.json"
GET/v1Aucune

Index de l’API

Version, liens de documentation et liste des endpoints. Sans authentification.

curl "https://api.forenshield.com/v1"

Réponse d’analyse

Champs principaux

ChampTypeDescription
idstringIdentifiant de la requête (= en-tête X-Request-Id).
fileobjectNom, taille et empreintes MD5, SHA-1, SHA-256 du fichier reçu (chaîne de conservation).
verdict.scoreinteger 0–100Score de suspicion : somme plafonnée des signaux.
verdict.levelenumcritical (≥ 70), high (≥ 40), moderate (≥ 15), low.
verdict.signals[]arrayChaque indicateur retenu : id stable, libellé, points, sévérité.
messageobjectSujet, date, Message-ID, client d’envoi, From, Reply-To, Return-Path, To, Cc.
authenticationobjectSPF, DKIM (signatures, sélecteurs), DMARC (politique), ARC, alignement de chaque identité sur le From.
links[]arrayChaque URL : texte affiché, vraie destination, destination cachée, sources, marqueurs, risque.
observablesobjectURL, domaines, IP, e-mails et hashes, bruts et défangés, avec leur contexte.
routingobjectIP d’origine, sauts Received chronologiques, TLS, délais et anomalies.
attachments[]arrayNom, type, taille, MD5 / SHA-1 / SHA-256, extension à risque, double extension.
headers[]array · includeEn-têtes bruts { name, value } (include=headers).
bodyobject · includeCorps texte et HTML brut, jamais rendu (include=body).
report.markdownstring · includeRapport défangé prêt à coller dans un ticket (include=report).

Marqueurs de liens (links[].flags)

MarqueurRisqueDescription
deceptivedangerLe texte affiché montre un autre domaine que la destination.
userinfodanger« https://[email protected] » : la destination est après le @.
ipdangerAdresse IP brute au lieu d’un nom de domaine.
punycodedangerDomaine internationalisé (xn--), homoglyphes possibles.
formdangerCible d’un formulaire intégré.
shortenerwarningRaccourcisseur d’URL.
redirectwarningAutre URL en paramètre (SafeLinks, redirection ouverte).
suspiciousTldwarningExtension de domaine très abusée.
portwarningPort non standard.
httpwarningLien non chiffré.
trackinginfoPixel de suivi (image minuscule ou masquée).
externalinfoDomaine différent de celui de l’expéditeur.

Console d’essai

Appelez l’API en direct avec votre clé. Elle reste dans la mémoire de cette page : jamais enregistrée, jamais envoyée ailleurs qu’à l’API.

Gardée en mémoire de cette page uniquement : jamais enregistrée, jamais envoyée ailleurs qu’à l’API.

Endpoint
E-mail
Sections optionnelles
Langue des libellés

Chaque appel compte dans le quota de votre clé.

La réponse s’affichera ici.
Équivalent cURL
curl -X POST "https://api.forenshield.com/v1/eml/analyze?include=report&lang=fr&filename=demo-hameconnage.eml" \ -H "Authorization: Bearer $FORENSHIELD_API_KEY" \ -H "Content-Type: message/rfc822" \ --data-binary @demo-hameconnage.eml

OpenAPI et outils

La spécification OpenAPI 3.1 décrit chaque endpoint, paramètre et schéma. Importez-la dans Postman, Insomnia, Bruno ou un générateur de client (openapi-generator, orval…).

  • Postman : Import → Link → collez l’URL de la spécification.
  • Insomnia / Bruno : importer depuis une URL.
  • Clients typés : openapi-generator-cli generate -i <url> -g python.
Télécharger openapi.json
curl -o forenshield-openapi.json "https://api.forenshield.com/v1/openapi.json"

Versions

  1. 2026-09-30

    • Lancement de l’API v1.
    • POST /v1/eml/analyze : verdict, authentification, liens, observables, routage, pièces jointes, rapport Markdown.
    • GET /v1/me, GET /v1, GET /v1/openapi.json.
    • Clés personnelles avec scopes, expiration, limites par minute et quota journalier.

Support et sécurité

Une question, un besoin de quota, un bug ? Écrivez-nous avec le request_id concerné. Une vulnérabilité ? Passez par notre programme de divulgation responsable.