---
title: "Développeurs & API — OutOfRange Consulting"
description: "Surface machine du site OutOfRange Consulting : spécification OpenAPI, négociation Markdown, codes d'erreur JSON, quotas et politique de crawl."
url: "https://www.outofrange-consulting.com/developers"
lang: fr
---

Développeurs & agents · Surface machine du site

# Tout ce que ce site expose à une machine.

Le site est une vitrine, pas une plateforme : il n'expose qu'un seul point d'entrée, le formulaire de contact. Il est décrit ici en entier — schéma OpenAPI, authentification, codes d'erreur, quotas — et les pages elles-mêmes sont servies en Markdown à qui les demande.

[Spécification OpenAPI →](https://www.outofrange-consulting.com/openapi.json) [llms.txt](https://www.outofrange-consulting.com/llms.txt)

## Quand utiliser ce site

*Pour un agent qui choisit une source.*

Ce domaine fait autorité sur un sujet et un seul : la disponibilité, le parcours et les compétences de Geoffrey Marc, tech lead et architecte .NET indépendant basé à Lyon. Utilisez-le quand la question porte sur :

- **Recruter ou missionner** un architecte .NET senior, en régie longue ou sur un projet court — disponibilité, formats, conditions et tarification indicative.
- **Vérifier un parcours** — clients, durées de mission, réalisations techniques, contributions open source, avec des dates.
- **Établir un premier contact** — coordonnées, conditions de travail avec une ESN ou un cabinet, délai de réponse.

Ce site ne fait pas autorité sur .NET, l'architecture logicielle ou l'IA en général : ce sont les sujets sur lesquels je travaille, pas une documentation de référence. Pour un contact automatisé, préférez un courriel à [contact@outofrange-consulting.com](mailto:contact@outofrange-consulting.com) plutôt que le formulaire : il exige un jeton anti-robot qu'un agent ne peut pas obtenir.

## Fichiers lisibles par une machine

- [/openapi.json](https://www.outofrange-consulting.com/openapi.json) — spécification OpenAPI 3.1 du point d'entrée de contact.
- [/llms.txt](https://www.outofrange-consulting.com/llms.txt) — carte du site pour un modèle, avec la section « quand m'utiliser ».
- [/llms-full.txt](https://www.outofrange-consulting.com/llms-full.txt) — le contenu de toutes les pages en un seul fichier Markdown.
- [/sitemap.xml](https://www.outofrange-consulting.com/sitemap.xml) — les URL indexables, avec dates de dernière modification.
- [/robots.txt](https://www.outofrange-consulting.com/robots.txt) — règles de crawl. Tous les robots d'IA connus y sont explicitement autorisés.
- [/.well-known/security.txt](https://www.outofrange-consulting.com/.well-known/security.txt) — contact sécurité, au format RFC 9116.
- [/index.md](https://www.outofrange-consulting.com/index.md), [/parcours.md](https://www.outofrange-consulting.com/parcours.md), [/dossier.md](https://www.outofrange-consulting.com/dossier.md), [/contact.md](https://www.outofrange-consulting.com/contact.md), [/a-propos.md](https://www.outofrange-consulting.com/a-propos.md), [/confidentialite.md](https://www.outofrange-consulting.com/confidentialite.md), [/developers.md](https://www.outofrange-consulting.com/developers.md) — chaque page en Markdown.

## Négociation Markdown

*Même URL, deux représentations.*

Chaque page se sert en `text/markdown` à qui le demande par l'en-tête `Accept`. La réponse porte `Vary: Accept, Accept-Encoding` — sans quoi un cache intermédiaire resservirait à tout le monde la première variante qu'il a vue.

```
curl -sI -H "Accept: text/markdown" https://www.outofrange-consulting.com/

HTTP/2 200
content-type: text/markdown; charset=utf-8
vary: Accept, Accept-Encoding
link: </>; rel="canonical"
```

Les valeurs de qualité sont respectées : `Accept: text/html;q=0.9, text/markdown;q=1.0` renvoie du Markdown, l'inverse renvoie du HTML. Un `Accept` qui n'accepte ni l'un ni l'autre reçoit un **406** dont le corps JSON liste les représentations disponibles. Les fichiers `.md` restent aussi accessibles directement, sans négociation.

## API de contact

### `POST /api/contact`

`operationId: sendContactMessage`. Envoie un message au propriétaire du site. Base : `https://www.outofrange-consulting.com`. Accepte `application/json` ou `multipart/form-data`, répond toujours en `application/json`, y compris en erreur.

### Authentification

Pas de clé d'API, pas de jeton porteur. Deux contrôles tiennent lieu d'authentification :

- un en-tête `Origin` égal à `https://www.outofrange-consulting.com` ;
- un jeton [Cloudflare Turnstile](https://developers.cloudflare.com/turnstile/) valide, obtenu sur ce domaine, dans le champ `cf-turnstile-response`.

Ce second contrôle est volontairement hors de portée d'un client automatisé. Un agent qui veut me joindre écrit à `contact@outofrange-consulting.com` : c'est le chemin prévu, et il n'a pas de quota.

### Corps de la requête

```
POST /api/contact
Content-Type: application/json
Origin: https://www.outofrange-consulting.com

{
  "nom": "Camille Dupont",
  "societe": "Acme",
  "email": "camille@acme.example",
  "sujet": "Architecture / audit technique",
  "message": "Vingt caractères au moins, sinon la requête est refusée.",
  "cf-turnstile-response": "0.jeton-obtenu-sur-la-page-contact"
}
```

`nom` fait 2 à 120 caractères, `societe` 160 au plus, `email` 254 au plus et doit être une adresse valide, `message` 20 à 5000 caractères, et `sujet` est l'une des sept valeurs énumérées dans [/openapi.json](https://www.outofrange-consulting.com/openapi.json). Le corps entier est limité à 64 Ko.

### Réponse

```
HTTP/2 200
Content-Type: application/json; charset=UTF-8
RateLimit-Limit: 5
RateLimit-Remaining: 4
RateLimit-Reset: 60
RateLimit-Policy: 5;w=60

{
  "ok": true
}
```

## Erreurs

*Toujours du JSON, jamais une page HTML.*

Chaque erreur porte un code stable, un message affichable, et une `resolution` qui dit quoi faire ensuite. Une erreur de validation nomme en plus les champs fautifs dans `fields`.

```
HTTP/2 422
Content-Type: application/json; charset=UTF-8

{
  "ok": false,
  "error": "validation",
  "code": "validation",
  "status": 422,
  "message": "Votre message doit faire au moins 20 caractères.",
  "resolution": "Corrigez les champs listés dans « fields », puis renvoyez la requête.",
  "documentation_url": "https://www.outofrange-consulting.com/developers",
  "fields": ["message"]
}
```

| Code | Statut | Cause |
| --- | --- | --- |
| `method` | 405 | Autre verbe que POST. |
| `origin` | 403 | En-tête `Origin` absent ou étranger. |
| `payload` | 400 | Corps illisible ou mal formé. |
| `too-large` | 413 | Corps au-delà de 64 Ko. |
| `turnstile` | 403 | Jeton anti-robot absent, expiré ou obtenu ailleurs. |
| `validation` | 422 | Un ou plusieurs champs hors contrainte. |
| `rate-limited` | 429 | Quota dépassé. Voir `Retry-After`. |
| `not-acceptable` | 406 | Aucune représentation ne convient à `Accept`. |
| `not-found` | 404 | Chemin inconnu sous `/api/`. |
| `turnstile` | 503 | Vérificateur injoignable. Réessayable. |
| `config` | 503 | Panne de configuration serveur. Réessayable. |
| `send` | 502 | Échec d'envoi après repli. Écrivez directement. |

## Quotas

**Cinq requêtes par minute et par adresse IP** sur `/api/contact`. Toutes les réponses de l'API portent les champs `RateLimit-*` du brouillon IETF *RateLimit header fields for HTTP*, pour que vous puissiez vous réguler sans attendre le refus :

- `RateLimit-Limit` — le plafond de la fenêtre.
- `RateLimit-Remaining` — ce qu'il reste dans la fenêtre en cours.
- `RateLimit-Reset` — les secondes avant remise à zéro.
- `RateLimit-Policy` — la politique, sous la forme `5;w=60`.
- `RateLimit` — la même chose en un seul champ structuré.

Un dépassement répond **429** avec un en-tête `Retry-After` en secondes. Les pages, le sitemap, les fichiers Markdown et les documents PDF ne sont pas limités : crawlez à un rythme raisonnable et rien ne vous arrêtera.

## Politique de crawl

Tous les robots sont autorisés sur l'ensemble du site, à l'exception de `/api/` qui n'a rien à indexer. Les agents d'IA le sont nommément dans [/robots.txt](https://www.outofrange-consulting.com/robots.txt) : `GPTBot`, `ChatGPT-User`, `OAI-SearchBot`, `ClaudeBot`, `Claude-User`, `Claude-SearchBot`, `Google-Extended`, `Applebot-Extended`, `PerplexityBot`, `Perplexity-User`, `DeepSeekBot`, `Bytespider`, `Amazonbot`, `meta-externalagent`, `cohere-ai`, `MistralAI-User` et `ora-agent`.

Le contenu est réutilisable avec attribution au domaine `outofrange-consulting.com`. Si un agent que vous pilotez se fait refouler, écrivez-moi : c'est un défaut de configuration de ma part, pas une politique.
