> For the complete documentation index, see [llms.txt](https://docs.ipcheck.ing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ipcheck.ing/developer/fr/reference/api-endpoints.md).

# Points de terminaison de l'API

{% hint style="warning" %}
**Il ne s’agit pas d’une API publique.** Ces routes existent pour servir le frontend de MyIP. Elles sont protégées par un `Referer` vérification ; leur structure peut changer sans préavis, et il n’existe ni versioning, ni politique d’obsolescence, ni contrat de stabilité. Ne construisez pas d’intégrations sur le `/api/*`. Cette page les documente afin que **vous puissiez exploiter et déboguer votre propre déploiement**.
{% endhint %}

Chaque route est définie dans `backend-server.js` et montée sur le serveur backend (`BACKEND_PORT`, par défaut `11966`). En production, `frontend-server.js` redirige `/api` depuis `FRONTEND_PORT` (par défaut `18966`) vers le backend, donc depuis l’extérieur du déploiement, tout vit sous `/api` une seule origine. Voir [Backend](/developer/fr/architecture/backend.md).

## Middleware global

Ils s’appliquent à **chaque** `/api/*` route, dans l’ordre de montage.

| Ordre | Middleware                         | Comportement                                                                                                                                                                   |
| ----- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 1     | `pino-http`                        | Uniquement lorsque `LOG_HTTP=true`. Journalise la méthode, l’URL et le statut. Monté avant les limiteurs afin que les 429 soient consignés.                                    |
| 2     | `express-rate-limit`               | Uniquement lorsque `SECURITY_RATE_LIMIT` est non nul. Maximum de N requêtes par IP par fenêtre de 20 minutes → `429 {"message":"Trop de requêtes"}`. Ignore `/api/monitoring`. |
| 3     | `express-slow-down`                | Uniquement lorsque `SECURITY_DELAY_AFTER` est non nul. Après N requêtes par IP par fenêtre de 60 minutes, ajoute `requêtes × 400 ms` de délai. Ignore `/api/monitoring`.       |
| 4     | `express.json({ limit: '500kb' })` | Analyse du corps JSON. Les corps de plus de 500 Ko reçoivent un `413`.                                                                                                         |
| 5     | `Cache-Control: no-store`          | **Valeur par défaut pour chaque route.** Les routes qui veulent une mise en cache en périphérie le remplacent explicitement.                                                   |
| 6     | `requireReferer`                   | Rejette toute requête dont le `Referer` nom d’hôte n’est pas `localhost` ou dans `ALLOWED_DOMAINS`.                                                                            |

### Filtre Referer

`requireReferer` est la première chose que rencontre chaque requête. La correspondance est une correspondance exacte du nom d’hôte avec `['localhost', ...ALLOWED_DOMAINS.split(',')]`.

| Condition                                      | Réponse                             |
| ---------------------------------------------- | ----------------------------------- |
| Aucun `Referer` en-tête du tout                | `403 {"error":"Que faites-vous ?"}` |
| `Referer` présent mais nom d’hôte non autorisé | `403 {"error":"Accès refusé"}`      |
| `Referer` impossible à analyser en URL         | `403 {"error":"Accès refusé"}`      |

C’est pourquoi `curl http://your-host:18966/api/configs` renvoie toujours 403 — curl n’envoie aucun `Referer`. Voir [Options de sécurité](/developer/fr/configuration/security-options.md).

### Mise en cache

Le `cacheable(seconds)` fabrique de middleware enveloppe `res.json` et définit `Cache-Control: public, max-age=<seconds>` **uniquement sur les réponses 2xx**, donc les erreurs ne sont jamais mises en cache en périphérie. Elle stocke aussi la valeur dans `res.locals.cacheControl` pour les gestionnaires qui diffusent du binaire et contournent `res.json` (seul `/api/map` le fait).

Tout ce qui n’est pas marqué comme cacheable hérite de la valeur globale `no-store` par défaut.

### Gardes

Les gardes se trouvent dans `common/guards.js` et sont appliquées par route. Elles rejettent toutes avec `400` et une chaîne JSON `d’erreur` .

| Garde                      | Lit                      | Vérifie                                                                                                                    | Erreurs                                                                           |
| -------------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `requireValidIP()`         | `?ip`                    | IPv4 ou IPv6 valide                                                                                                        | `Aucune adresse IP fournie` / `Adresse IP invalide`                               |
| `requireValidDomain()`     | `?domain`                | Domaine syntaxique ; met la valeur en minuscules sur place afin que le cache en périphérie voie une forme canonique unique | `Aucun domaine fourni` / `Domaine invalide`                                       |
| `requireValidPrefix()`     | `?prefix`                | CIDR bien formé (quelle que soit la longueur — le frontend décide de la quantification)                                    | `Aucun préfixe fourni` / `Préfixe invalide`                                       |
| `requireValidASN()`        | `?asn`                   | Numérique, facultatif `AS` préfixe ; supprime le préfixe sur place                                                         | `Aucun ASN fourni` / `ASN invalide`                                               |
| `requireValidProviderId()` | `?id`                    | Appartenance à la liste autorisée des identifiants de fournisseur de l’état des services                                   | `Aucun identifiant de fournisseur fourni` / `Identifiant de fournisseur invalide` |
| `requireValidReportId()`   | paramètre de route `:id` | Exactement 22 caractères base64url (16 octets aléatoires)                                                                  | `Identifiant de rapport invalide`                                                 |

## Géolocalisation IP

Toutes renvoient la même structure normalisée (`ip`, `city`, `region`, `country`, `country_name`, `country_code`, `latitude`, `longitude`, `asn`, `org`), produite par la `makeGeoHandler` fabrique dans `common/geo-handler.js`. Voir [Sources de données IP](/developer/fr/architecture/ip-data-sources.md).

| Route                  | Paramètres                     | Garde · Cache               | Objectif                                                                                                                                                         |
| ---------------------- | ------------------------------ | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /api/ipinfo`      | `ip`                           | `requireValidIP` · 1 jour   | Géolocalisation via ipinfo.io. `IPINFO_API_KEY` facultative.                                                                                                     |
| `GET /api/ipapicom`    | `ip`, `lang` (par défaut `en`) | `requireValidIP` · 1 jour   | Géolocalisation via ip-api.com. Aucune clé.                                                                                                                      |
| `GET /api/ipsb`        | `ip`                           | `requireValidIP` · 1 jour   | Géolocalisation via api.ip.sb. Aucune clé.                                                                                                                       |
| `GET /api/ipapiis`     | `ip`                           | `requireValidIP` · 1 jour   | Géolocalisation via api.ipapi.is ; renvoie aussi `isHosting` / `isProxy`. Nécessite `IPAPIIS_API_KEY`.                                                           |
| `GET /api/ip2location` | `ip`                           | `requireValidIP` · 1 jour   | Géolocalisation via ip2location.io. Nécessite `IP2LOCATION_API_KEY`.                                                                                             |
| `GET /api/maxmind`     | `ip`, `lang` (par défaut `en`) | `requireValidIP` · 1 jour   | Recherche locale GeoLite2 City + ASN. Nécessite des identifiants MaxMind ou préremplie `.mmdb`; **503** lorsque les bases de données ne sont pas chargées.       |
| `GET /api/ipchecking`  | `ip`, `lang` (par défaut `en`) | `requireValidIP` · no-store | Géolocalisation via l’API privée IPCheck.ing. Nécessite `IPCHECKING_API_KEY` + `IPCHECKING_API_ENDPOINT`; `500 {"error":"La clé API est manquante"}` sans elles. |

`lang` sur `/api/maxmind` est validé par rapport à `['zh-CN', 'en', 'fr', 'ru']`; tout le reste retombe sur `en`. `lang` sur `/api/ipapicom` et `/api/ipchecking` est transmis vers l’amont sans validation.

Les échecs en amont sur les gestionnaires de géolocalisation renvoient `500 {"error": "<message>"}`.

## Outils réseau

| Route                                 | Paramètres                                                                                    | Garde · Cache                 | Objectif                                                                                                                                                                                                          |
| ------------------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /api/whois`                      | `q` (IP ou domaine)                                                                           | intégré · 1 jour              | Recherche WHOIS / RDAP. Les IP vont d’abord vers RDAP avec `whoiser` comme solution de repli.                                                                                                                     |
| `GET /api/dnsresolver`                | `hostname`, `type`                                                                            | intégré · no-store            | Résout un nom d’hôte en parallèle via plusieurs résolveurs DNS classiques et DoH, pour comparer la contamination.                                                                                                 |
| `GET /api/dnsleaktest/session/:token` | route `:token` (32 caractères hexadécimaux), `lang` (par défaut `zh-CN`)                      | intégré · no-store            | Récupère un résultat de session DNS-leak enrichi. Transmet les en-têtes de requête (y compris `Authorization`) et relaie le statut en amont tel quel. Nécessite `IPCHECKING_API_KEY` + `IPCHECKING_API_ENDPOINT`. |
| `GET /api/ooni-blocking`              | `domain`                                                                                      | `requireValidDomain` · 1 jour | Agrégat de censure OONI sur une fenêtre UTC de 30 jours ; interroge à la fois l’apex et le `www.` variant [www](http://www). et fusionne.                                                                         |
| `GET /api/globalping-probes`          | —                                                                                             | — · 7 jours                   | Inventaire concis des sondes Globalping en ligne par pays, pour les sélecteurs de pays MTR / latence / censure.                                                                                                   |
| `GET /api/macchecker`                 | `mac` (exactement 12 caractères hexadécimaux après suppression de `:` et `-`)                 | intégré · 30 jours            | Recherche de fournisseur IEEE OUI via maclookup.app. `MAC_LOOKUP_API_KEY` facultative.                                                                                                                            |
| `GET /api/map`                        | `latitude`, `longitude`, `language` (2 lettres), `CanvasMode` (`Sombre` pour le style sombre) | intégré · 1 an                | Relaye un JPEG Google Static Maps. **Renvoie des données binaires**, pas du JSON. Nécessite `GOOGLE_MAP_API_KEY`.                                                                                                 |
| `GET /api/invisibility`               | `id` (28 caractères alphanumériques)                                                          | intégré · no-store            | Interroge le résultat de détection de proxy. Un 404 en amont est traduit en `200 {"status":"en attente"}`. Nécessite `IPCHECKING_API_KEY` + `IPCHECKING_API_ENDPOINT`.                                            |

## ASN et BGP

| Route                       | Paramètres      | Garde · Cache                   | Objectif                                                                                                                                                                                                                               |
| --------------------------- | --------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /api/cfradar`          | `asn`           | intégré · 30 jours              | Segments de trafic / adoption Cloudflare Radar pour un ASN. Les échecs partiels des segments sont consignés et servis ; un échec total renvoie 500. Nécessite `CLOUDFLARE_API_KEY`.                                                    |
| `GET /api/asn-history`      | `prefix` (CIDR) | `requireValidPrefix` · 30 jours | Annonces BGP historiques pour un préfixe, depuis routing-history de RIPEstat, avec des pourcentages de visibilité relatifs. Les réponses en amont non-2xx renvoient `502 {"error":"Erreur amont"}`. `RIPESTAT_SOURCE_APP` facultative. |
| `GET /api/asn-connectivity` | `asn`           | `requireValidASN` · 30 jours    | Graphe topologique amont depuis un ASN vers les backbones Tier-1, construit à partir du snapshot local CAIDA as-rel.                                                                                                                   |

## État des services

Les deux gestionnaires lisent un instantané en mémoire maintenu par un collecteur en arrière-plan selon un calendrier fixe de 5 minutes. Aucun ne contacte l’amont au moment de la requête, donc le volume de requêtes n’affecte jamais la charge en amont.

| Route                            | Paramètres                 | Garde · Cache                    | Objectif                                                                    |
| -------------------------------- | -------------------------- | -------------------------------- | --------------------------------------------------------------------------- |
| `GET /api/service-status`        | —                          | — · 5 min                        | Aperçu : un voyant d’état par fournisseur, sans lourds tableaux de détails. |
| `GET /api/service-status/detail` | `id` (slug du fournisseur) | `requireValidProviderId` · 5 min | Les sous-composants d’un fournisseur ainsi que les incidents récents.       |

## Plateforme

| Route                            | Paramètres                                                      | Garde · Cache                                         | Objectif                                                                                                                              |
| -------------------------------- | --------------------------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /api/configs`               | —                                                               | — · 1 heure                                           | Indicateurs de fonctionnalité pour le frontend. Renvoie **uniquement des booléens**, jamais les valeurs des clés.                     |
| `GET /api/github-stars`          | —                                                               | — · 1 jour                                            | Nombre d’étoiles pour `jason5ng32/MyIP`, récupéré sans authentification.                                                              |
| `GET /api/getuserinfo`           | — (transmet les en-têtes de requête, y compris `Authorization`) | — · no-store                                          | Profil de l’utilisateur connecté depuis l’API compagnon. Nécessite `IPCHECKING_API_KEY` + `IPCHECKING_API_ENDPOINT`.                  |
| `PUT /api/updateuserachievement` | corps JSON                                                      | — · no-store                                          | Enregistre le déverrouillage d’un succès. Nécessite `IPCHECKING_API_KEY` + `IPCHECKING_API_ENDPOINT`.                                 |
| `POST /api/report`               | corps JSON `{ report, ttlDays }`                                | liste blanche du schéma + limite de taille · no-store | Stocke un rapport de diagnostic partageable dans Workers KV et renvoie son identifiant. Nécessite les trois `CLOUDFLARE_*` variables. |
| `GET /api/report/:id`            | route `:id` (22 caractères)                                     | `requireValidReportId` · no-store                     | Lit un rapport stocké pour le `/r/:id` page. Nécessite les mêmes trois `CLOUDFLARE_*` variables.                                      |
| `POST /api/monitoring`           | corps brut de l’enveloppe (10 Mo max)                           | limiteur propre · no-store                            | Tunnel Sentry de première partie. **Monté uniquement lorsque `VITE_SENTRY_DSN_FRONTEND` est défini.**                                 |

### `/api/configs` réponse

Chaque champ est un booléen. `originalSite` est `vrai` uniquement lorsque le `Referer` nom d’hôte est l’un des noms d’hôte canoniques d’IPCheck.ing.

{% code title="GET /api/configs" %}

```json
{
  "map": false,
  "ipInfo": false,
  "ipChecking": false,
  "ip2location": false,
  "originalSite": false,
  "cloudFlare": false,
  "ipapiis": false,
  "reportSharing": false
}
```

{% endcode %}

### Codes de statut du partage de rapports

| Code  | Signification                                                                                            |
| ----- | -------------------------------------------------------------------------------------------------------- |
| `503` | Les trois `CLOUDFLARE_*` variables ne sont pas toutes définies.                                          |
| `400` | Le corps du rapport a échoué à la validation du schéma (`{"error":"Rapport invalide","details":[...]}`). |
| `413` | Le rapport sérialisé dépasse 256 Ko.                                                                     |
| `404` | Sur `GET`: rapport introuvable ou son TTL KV a expiré.                                                   |

`ttlDays` doit être `1`, `3` ou `7`; toute autre valeur est silencieusement ramenée à `1`.

### `/api/monitoring`

Monté uniquement lorsque `VITE_SENTRY_DSN_FRONTEND` est défini sur le **processus backend**. Il dispose d’un limiteur dédié de 600 requêtes par IP par fenêtre de 20 minutes et est explicitement ignoré par les deux limiteurs globaux — le partage du quota de l’application avec la télémétrie est la raison pour laquelle le signalement des erreurs cesse silencieusement de fonctionner. Le corps est analysé avec `express.raw` en utilisant un matcher de type générique, car les enveloppes Sentry Replay sont envoyées sans `Content-Type` du tout.

## Résumé des TTL de cache

| TTL        | Routes                                                                                                                                                                                                               |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 5 minutes  | `/api/service-status`, `/api/service-status/detail`                                                                                                                                                                  |
| 1 heure    | `/api/configs`                                                                                                                                                                                                       |
| 1 jour     | `/api/ipinfo`, `/api/ipapicom`, `/api/ipsb`, `/api/ipapiis`, `/api/ip2location`, `/api/maxmind`, `/api/whois`, `/api/github-stars`, `/api/ooni-blocking`                                                             |
| 7 jours    | `/api/globalping-probes`                                                                                                                                                                                             |
| 30 jours   | `/api/cfradar`, `/api/asn-history`, `/api/asn-connectivity`, `/api/macchecker`                                                                                                                                       |
| 1 an       | `/api/map`                                                                                                                                                                                                           |
| `no-store` | tout le reste — `/api/ipchecking`, `/api/dnsresolver`, `/api/dnsleaktest/session/:token`, `/api/invisibility`, `/api/getuserinfo`, `/api/updateuserachievement`, `/api/report`, `/api/report/:id`, `/api/monitoring` |

Les TTL sont choisis en fonction du rythme naturel de rafraîchissement de chaque source en amont. Les rapports partagés restent `no-store` délibérément : un cache de bord pourrait servir un rapport après l’expiration de son KV, et les données de diagnostic privées n’ont pas leur place dans un cache public.

## Non-`/api` routes

`frontend-server.js` sert tout le reste : la sortie statique `dist/` avec, par classe d’asset, `Cache-Control`, et un repli d’historique SPA qui renvoie `index.html` (avec `no-store`) pour les navigations GET dont le dernier segment de chemin n’a pas d’extension de fichier.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ipcheck.ing/developer/fr/reference/api-endpoints.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
