Continuer → Aperçu

Référence API REST

Quelques endpoints, une seule forme de réponse. Tout ci-dessous est actif sur votre compte.

https://namegender.com/api/v1/gender S'inscrire gratuitement
llms-full.txt

Markdown pour les assistants de code comme Claude Code, Cursor et Copilot. Collez-le dans la conversation ou donnez le lien à l'assistant.

Démarrage rapide

Créez une clé dans votre tableau de bord, puis envoyez votre première requête. Aucun SDK nécessaire.

curl "https://namegender.com/api/v1/gender?name=Ay%C5%9Fe&country=TR" \
  -H "Authorization: Bearer YOUR_API_KEY"
<?php

$query = http_build_query(['name' => 'Ayşe', 'country' => 'TR']);

$ch = curl_init('https://namegender.com/api/v1/gender?' . $query);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer YOUR_API_KEY'],
]);

$result = json_decode(curl_exec($ch), true);

echo $result['gender'];       // female
echo $result['probability'];  // 100
const params = new URLSearchParams({ name: 'Ayşe', country: 'TR' });

const response = await fetch(`https://namegender.com/api/v1/gender?${params}`, {
  headers: { Authorization: 'Bearer YOUR_API_KEY' },
});

const result = await response.json();

console.log(result.gender);       // "female"
console.log(result.probability);  // 100
import requests

response = requests.get(
    "https://namegender.com/api/v1/gender",
    params={"name": "Ayşe", "country": "TR"},
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)

result = response.json()
print(result["gender"])       # female
print(result["probability"])  # 100
require "net/http"
require "json"

uri = URI("https://namegender.com/api/v1/gender")
uri.query = URI.encode_www_form(name: "Ayşe", country: "TR")

request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer YOUR_API_KEY"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

puts JSON.parse(response.body)["gender"]   # female
req, _ := http.NewRequest("GET", "https://namegender.com/api/v1/gender?name=Ay%C5%9Fe&country=TR", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")

resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

var result struct {
    Gender      string `json:"gender"`
    Probability int    `json:"probability"`
}
json.NewDecoder(resp.Body).Decode(&result)

fmt.Println(result.Gender)   // female

Chaque endpoint retourne la même structure, vous pouvez donc changer les entrées sans modifier votre code d'analyse.

Authentification

Chaque requête transmet votre clé API dans un header. Utilisez Authorization: Bearer par défaut, ou X-Api-Key si votre client HTTP réserve le header Authorization à autre chose. Une clé placée dans l'URL est refusée : les URL sont recopiées dans les journaux de proxy, les outils d'analyse et l'historique du navigateur.

Header Authorization (recommandé)
Authorization: Bearer ng_live_xxxxxxxxxxxx

Échec de la copie. Sélectionnez et copiez le texte.

Header X-Api-Key
X-Api-Key: ng_live_xxxxxxxxxxxx

Échec de la copie. Sélectionnez et copiez le texte.

N'exposez jamais votre clé dans du code côté client. Les appels depuis un navigateur ou une application mobile doivent passer par votre propre backend.

Vous pouvez restreindre une clé à des adresses IP spécifiques depuis le tableau de bord.

Bibliothèques client

De minces wrappers sur l'API REST. Ils envoient votre clé, construisent chaque requête et transforment les réponses d'erreur en exceptions.

JavaScript Source
npm install namegender

Échec de la copie. Sélectionnez et copiez le texte.

Command line Source
npm install -g namegender

Échec de la copie. Sélectionnez et copiez le texte.

composer require namegender/namegender

Échec de la copie. Sélectionnez et copiez le texte.

Python Source
pip install namegender-client

Échec de la copie. Sélectionnez et copiez le texte.

gem install namegender

Échec de la copie. Sélectionnez et copiez le texte.

<repository>
  <id>jitpack.io</id>
  <url>https://jitpack.io</url>
</repository>

<dependency>
  <groupId>com.github.anpekesen</groupId>
  <artifactId>namegender-java</artifactId>
  <version>v0.9.0</version>
</dependency>

Échec de la copie. Sélectionnez et copiez le texte.

C# / .NET Source
dotnet add package NameGender --version 0.6.0

Échec de la copie. Sélectionnez et copiez le texte.

go get github.com/anpekesen/namegender-go@v0.7.0

Échec de la copie. Sélectionnez et copiez le texte.

remotes::install_github('anpekesen/namegender-r', ref = 'v0.7.0')

Échec de la copie. Sélectionnez et copiez le texte.

PowerShell Source
Install-Module NameGender

Échec de la copie. Sélectionnez et copiez le texte.

cargo add namegender

Échec de la copie. Sélectionnez et copiez le texte.

Vous n'en avez pas besoin. L'API se résume à quelques endpoints en JSON simple ; une bibliothèque vous fait gagner un après-midi, pas un projet. Si votre langage n'est pas listé, la référence REST contient des exemples à copier-coller.

Voir tout

Assistants IA (MCP)

Utilisez NameGender depuis Claude, Cursor et tout autre client compatible avec le Model Context Protocol. Interrogez l'assistant sur une liste de noms et il appelle l'API pour vous, avec les éléments de preuve à côté de chaque réponse.

Claude Code
claude mcp add namegender -e NAMEGENDER_API_KEY=ng_live_... -- npx -y namegender-mcp

Échec de la copie. Sélectionnez et copiez le texte.

Claude Desktop, Cursor et autres clients
{
    "mcpServers": {
        "namegender": {
            "command": "npx",
            "args": [
                "-y",
                "namegender-mcp"
            ],
            "env": {
                "NAMEGENDER_API_KEY": "ng_live_..."
            }
        }
    }
}

Échec de la copie. Sélectionnez et copiez le texte.

Ajoutez ceci au fichier de configuration MCP du client, puis redémarrez-le.

Outils

gender_from_name
Genre à partir d'un prénom ou d'un nom complet.
gender_from_email
Lit le nom dans une adresse email ; les adresses génériques comme info@ renvoient inconnu.
gender_from_username
Lit le nom dans un nom d'utilisateur ou un pseudo.
gender_bulk
Jusqu'à 100 valeurs en une seule requête, avec un résumé du taux de correspondance.
name_countries
Pays où un nom est enregistré. Ce n'est pas une affirmation sur son origine.
salutation
Formule d'appel d'une lettre dans la langue de la lettre ; la forme neutre quand le genre n'est pas certain.
name_check
Indique si un nom saisi dans un formulaire semble réel, avec les raisons. Ne qualifie jamais un nom de faux.
age_from_name
Âge médian et tranches d'âge des personnes portant un prénom aux États-Unis, en France et en Norvège.
account_status
Crédits restants et allocation gratuite du jour.

Chaque recherche consomme des crédits du compte propriétaire de la clé, exactement comme un appel direct à l'API. Référencé dans le registre MCP officiel sous le nom io.github.anpekesen/namegender. Paquet npm · Source

GET · POST https://namegender.com/api/v1/gender
Markdown

Genre à partir du nom

Accepte un prénom ou un nom complet. Les titres, prénoms supplémentaires et noms de famille sont supprimés avant la recherche, donc « Dr. Ayşe Yılmaz » et « Ayşe » donnent la même réponse.

Paramètre Type Description
name
requis
string Le nom à classifier. Prénom ou nom complet.
country
optionnel
string Code de pays ISO 3166-1 alpha-2. Améliore la précision pour les noms dont le genre varie selon la région, comme Andrea (masculin en Italie, féminin en Allemagne).
locale
optionnel
string Une balise de langue comme de-DE ou en_US, par exemple la langue du navigateur. Sa région devient le pays quand country n'est pas envoyé. Une balise sans région (en, de) ne fixe aucun pays.
ip
optionnel
string L'adresse IP de l'utilisateur final. Son pays est utilisé quand ni country ni une locale avec région ne sont envoyés. Non conservée. IP geolocation by DB-IP (db-ip.com).
ai_fallback
optionnel
boolean Si le nom n'a aucune entrée dans nos données, demander une estimation à un modèle de langage au lieu de retourner null. Ne fonctionne qu'une fois les recherches IA activées dans vos paramètres, et coûte un crédit supplémentaire.
best_guess
optionnel
boolean Retourner le genre dominant même lorsque les données n'atteignent pas le seuil de confiance. Désactivé par défaut : une réponse proche du 50/50 qui paraît certaine fait plus de dégâts qu'un null.
curl "https://namegender.com/api/v1/gender?name=Jordan" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "credits_charged": 1,
  "credits_remaining": 49999,
  "request_id": "req_4b7e0c2d9a1f6358",
  "query": "Jordan",
  "name": "Jordan",
  "first_name": "Jordan",
  "middle_name": null,
  "last_name": null,
  "name_type": "personal",
  "gender": "male",
  "country": null,
  "sample_size": 62240,
  "probability": 84,
  "took_ms": 1,
  "confidence": "high",
  "source": "db",
  "matched_as": null
}
GET · POST https://namegender.com/api/v1/gender/email
Markdown

Genre à partir de l'email

Extrait la personne de la partie locale de l'adresse, puis la classe. « ayse.yilmaz84@example.com » correspond à Ayşe.

Paramètre Type Description
email
requis
string L'adresse email. Seule la partie avant @ est utilisée.
country
optionnel
string Code de pays ISO 3166-1 alpha-2. Améliore la précision pour les noms dont le genre varie selon la région, comme Andrea (masculin en Italie, féminin en Allemagne).
locale
optionnel
string Une balise de langue comme de-DE ou en_US, par exemple la langue du navigateur. Sa région devient le pays quand country n'est pas envoyé. Une balise sans région (en, de) ne fixe aucun pays.
ip
optionnel
string L'adresse IP de l'utilisateur final. Son pays est utilisé quand ni country ni une locale avec région ne sont envoyés. Non conservée. IP geolocation by DB-IP (db-ip.com).
ai_fallback
optionnel
boolean Si le nom n'a aucune entrée dans nos données, demander une estimation à un modèle de langage au lieu de retourner null. Ne fonctionne qu'une fois les recherches IA activées dans vos paramètres, et coûte un crédit supplémentaire.
best_guess
optionnel
boolean Retourner le genre dominant même lorsque les données n'atteignent pas le seuil de confiance. Désactivé par défaut : une réponse proche du 50/50 qui paraît certaine fait plus de dégâts qu'un null.

best_guess s'applique au prénom lu dans l'adresse, pas à l'adresse elle-même. Si aucun prénom ne peut être lu, il n'y a rien à forcer et gender reste null. Gardez à l'esprit qu'une réponse forcée repose ici sur une extraction qui peut elle-même être erronée.

curl "https://namegender.com/api/v1/gender/email?email=ayse.yilmaz84%40example.com" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "credits_charged": 1,
  "credits_remaining": 49998,
  "query": "ayse.yilmaz84@example.com",
  "name": "Ayse",
  "gender": "female",
  "sample_size": 655,
  "probability": 100,
  "took_ms": 1,
  "confidence": "high",
  "source": "db"
}
GET · POST https://namegender.com/api/v1/gender/username
Markdown

Genre à partir de l'identifiant

Gère camelCase, snake_case, les chiffres à la fin et les @ en début. « AyseYilmaz84 » correspond à Ayşe.

Paramètre Type Description
username
requis
string L'identifiant ou le nom d'utilisateur. Un @ au début est ignoré.
country
optionnel
string Code de pays ISO 3166-1 alpha-2. Améliore la précision pour les noms dont le genre varie selon la région, comme Andrea (masculin en Italie, féminin en Allemagne).
locale
optionnel
string Une balise de langue comme de-DE ou en_US, par exemple la langue du navigateur. Sa région devient le pays quand country n'est pas envoyé. Une balise sans région (en, de) ne fixe aucun pays.
ip
optionnel
string L'adresse IP de l'utilisateur final. Son pays est utilisé quand ni country ni une locale avec région ne sont envoyés. Non conservée. IP geolocation by DB-IP (db-ip.com).
ai_fallback
optionnel
boolean Si le nom n'a aucune entrée dans nos données, demander une estimation à un modèle de langage au lieu de retourner null. Ne fonctionne qu'une fois les recherches IA activées dans vos paramètres, et coûte un crédit supplémentaire.
best_guess
optionnel
boolean Retourner le genre dominant même lorsque les données n'atteignent pas le seuil de confiance. Désactivé par défaut : une réponse proche du 50/50 qui paraît certaine fait plus de dégâts qu'un null.
curl "https://namegender.com/api/v1/gender/username?username=AyseYilmaz84" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "credits_charged": 1,
  "credits_remaining": 49997,
  "query": "AyseYilmaz84",
  "name": "Ayse",
  "gender": "female",
  "sample_size": 655,
  "probability": 100,
  "took_ms": 1,
  "confidence": "high",
  "source": "db"
}
POST https://namegender.com/api/v1/gender/bulk
Markdown

Requête en masse

Envoyez jusqu'à 100 noms dans une seule requête. Utilisez ceci au lieu de boucler : un appel en masse pour 100 noms est un seul aller-retour et une recherche dédupliquée.

Paramètre Type Description
names
requis
string[] Tableau de noms. Maximum 100 éléments.
type
optionnel
string Ce que sont les éléments : name, email ou username. Par défaut name.
country
optionnel
string Appliqué à chaque élément de la requête.
locale
optionnel
string Balise de langue dont la région devient le pays de chaque élément quand country n'est pas envoyé.
ip
optionnel
string Adresse IP de l'utilisateur final dont le pays s'applique à chaque élément quand ni country ni une locale avec région ne sont envoyés. Non conservée. IP geolocation by DB-IP (db-ip.com).
curl -X POST "https://namegender.com/api/v1/gender/bulk" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"names": ["Ayşe", "Mehmet", "Priya", "Wei"]}'
<?php

$ch = curl_init('https://namegender.com/api/v1/gender/bulk');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'names' => ['Ayşe', 'Mehmet', 'Priya', 'Wei'],
    ]),
]);

$data = json_decode(curl_exec($ch), true);

foreach ($data['results'] as $row) {
    printf("%-8s %-7s %d%%\n", $row['query'], $row['gender'] ?? '?', $row['probability']);
}
const response = await fetch('https://namegender.com/api/v1/gender/bulk', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ names: ['Ayşe', 'Mehmet', 'Priya', 'Wei'] }),
});

const { results, summary } = await response.json();

console.log(summary.match_rate);   // 100
results.forEach(r => console.log(r.query, r.gender, r.probability));
import requests

response = requests.post(
    "https://namegender.com/api/v1/gender/bulk",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={"names": ["Ayşe", "Mehmet", "Priya", "Wei"]},
)

data = response.json()
print(data["summary"]["match_rate"])   # 100

for row in data["results"]:
    print(row["query"], row["gender"], row["probability"])
{
  "credits_charged": 4,
  "credits_remaining": 49995,
  "request_id": "req_71d0a9e3c5b24f86",
  "took_ms": 2,
  "summary": {
    "total": 4,
    "identified": 4,
    "unknown": 0,
    "match_rate": 100
  },
  "results": [
    { "query": "Ayşe",   "gender": "female", "probability": 100, "sample_size":  655, "confidence": "high", "source": "db" },
    { "query": "Mehmet", "gender": "male",   "probability": 100, "sample_size": 1130, "confidence": "high", "source": "db" },
    { "query": "Priya",  "gender": "female", "probability": 100, "sample_size": 2993, "confidence": "high", "source": "db" },
    { "query": "Wei",    "gender": "male",   "probability":  86, "sample_size":  136, "confidence": "high", "source": "db" }
  ]
}

Les résultats sont retournés dans le même ordre que celui dans lequel vous les avez envoyés. Les crédits sont débités par nom, et l'intégralité de la requête est rejetée avant tout traitement si votre solde est insuffisant, donc vous n'obtiendrez jamais un lot partiellement traité.

Le bloc de résumé vous montre le taux de correspondance d'un coup d'œil, pour que vous puissiez décider si l'entrée a besoin d'être nettoyée avant de traiter le reste.

POST GET DELETE https://namegender.com/api/v1/batches
Markdown

Tâches de fichier

Envoyez un fichier CSV ou XLSX de 100 Mo et 1 000 000 lignes au maximum et récupérez-le avec des colonnes de genre ajoutées à chaque ligne. Un crédit par ligne, facturé uniquement si la tâche aboutit.

  1. 1. POST /batches Envoyez le fichier et name_column. La tâche est mise en file immédiatement.
  2. 2. GET /batches/{id} Lisez la tâche jusqu'à ce que status soit completed ou failed. poll_after_seconds indique combien attendre entre deux lectures.
  3. 3. GET /batches/{id}/result Téléchargez le résultat. Il revient dans le format envoyé.
Paramètre Type Description
file
requis
file CSV, TSV ou XLSX avec une ligne d'en-tête.
name_column
requis
string En-tête de la colonne contenant les noms, tel qu'il figure dans le fichier. Obligatoire sauf si start=false.
country_column
optionnel
string En-tête d'une colonne contenant un code pays par ligne.
country
optionnel
string Pays par défaut pour les lignes qui n'en ont pas.
ai_fallback
optionnel
boolean Interroger un modèle d'IA pour les noms absents du jeu de données. Nécessite le consentement IA dans les Paramètres.
best_guess
optionnel
boolean Renvoyer le genre le plus probable même lorsque les indices sont faibles.
delete_after_download
optionnel
boolean Le résultat peut être téléchargé une seule fois, puis il est supprimé.
start
optionnel
boolean false : envoyer et inspecter seulement. true par défaut.
# 1. Upload and start
curl -X POST "https://namegender.com/api/v1/batches" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: 6f1c2e0a-customers-2026-09" \
  -F "file=@customers.csv" \
  -F "name_column=first_name" \
  -F "country_column=country"

# 2. Poll until status is completed or failed
curl "https://namegender.com/api/v1/batches/B-7K2M9QX4TA" \
  -H "Authorization: Bearer YOUR_API_KEY"

# 3. Download the result
curl "https://namegender.com/api/v1/batches/B-7K2M9QX4TA/result" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o customers-gender.csv
import { NameGender } from 'namegender';
import { openAsBlob } from 'node:fs';
import { writeFile } from 'node:fs/promises';

const client = new NameGender(process.env.NAMEGENDER_API_KEY);

const job = await client.batches.create(await openAsBlob('customers.csv'), {
  filename: 'customers.csv',
  name_column: 'first_name',
  country_column: 'country',
});

const done = await client.batches.wait(job.id);
if (done.status === 'failed') throw new Error(done.error.code);

const file = await client.batches.download(done.id);
await writeFile('customers-gender.csv', Buffer.from(await file.arrayBuffer()));
from namegender import NameGender

client = NameGender("YOUR_API_KEY")

job = client.batches.create("customers.csv", name_column="first_name", country_column="country")

done = client.batches.wait(job["id"])
if done["status"] == "failed":
    raise RuntimeError(done["error"]["code"])

client.batches.download(done["id"], "customers-gender.csv")
{
  "id": "B-7K2M9QX4TA",
  "status": "completed",
  "source": "api",
  "file": { "name": "customers.csv", "format": "csv" },
  "columns": { "name": "first_name", "country": "country" },
  "rows": { "total": 200000, "processed": 200000, "identified": 187412 },
  "progress": 100,
  "credits": { "reserved": 200000, "charged": 200000 },
  "summary": { "male": 96120, "female": 91292, "unknown": 12588, "from_llm": 0 },
  "error": null,
  "result": {
    "url": "https://namegender.com/api/v1/batches/B-7K2M9QX4TA/result",
    "format": "csv",
    "expires_at": "2026-10-01T10:04:12Z"
  },
  "poll_after_seconds": null
}

name_column est obligatoire pour lancer la tâche : une colonne devinée qui se révèle fausse dépenserait des crédits sur les mauvaises données. Envoyez start=false pour obtenir d'abord les colonnes, un aperçu et le coût, puis lancez la tâche.

Envoyez un en-tête Idempotency-Key. Une nouvelle tentative avec la même clé renvoie la première tâche au lieu d'en ouvrir une seconde.

Jusqu'à 3 tâches peuvent être en file ou en cours en même temps. Une tâche non lancée peut être annulée et son crédit est restitué ; une tâche en cours ne peut pas être arrêtée.

POST https://your-server.example/…
Markdown

Webhooks

Ajoutez un point de terminaison dans Webhooks de votre tableau de bord : nous lui envoyons un POST signé quand une tâche de fichier se termine ou échoue, sans que vous ayez à interroger.

Événement Type Description
batch.completed BatchJob La tâche est terminée. Le corps contient la tâche exactement comme GET /batches/{id} la renvoie.
batch.failed BatchJob La tâche a échoué et n'a pas été facturée. Branchez sur error.code.
credits.low CreditsAlert Au rythme actuel, les crédits durent 7 jours ou moins. Vérifié toutes les heures ; les renouvellements d'abonnement sont pris en compte.
credits.depleted CreditsAlert Le solde est vide et les requêtes sont refusées avec 402. Vérifié toutes les heures.
webhook.test object Envoyé uniquement par « Envoyer un événement de test » dans le tableau de bord, et seulement à ce point de terminaison.
En-tête Type Description
NameGender-Signature
requis
string t=<secondes unix>,v1=<hex>. Un second v1 apparaît pendant 24 heures après le renouvellement du secret.
NameGender-Event-Id
requis
string L'identifiant de l'événement. Identique à chaque nouvel essai du même événement.
NameGender-Delivery-Attempt
requis
integer 1 au premier essai, jusqu'à 8.

Vérifiez chaque requête

v1 est le HMAC-SHA256 de l'horodatage, d'un point et du corps brut, avec le secret de votre point de terminaison. Comparez en temps constant, acceptez la requête si un v1 correspond, et refusez un horodatage éloigné de plus de cinq minutes de votre horloge. Les bibliothèques clientes font tout cela en un appel.

Vérifiez le corps tel qu'il est reçu. Un framework qui analyse le JSON puis le resérialise modifie les octets, et la signature ne correspond plus.
import express from 'express';
import { webhooks, NameGenderWebhookError } from 'namegender';

const app = express();

// express.raw, not express.json: the signature covers the exact bytes.
app.post('/namegender', express.raw({ type: 'application/json' }), async (req, res) => {
  let event;
  try {
    event = await webhooks.verify(
      req.body,
      req.get('NameGender-Signature'),
      process.env.NAMEGENDER_WEBHOOK_SECRET,
    );
  } catch (error) {
    if (error instanceof NameGenderWebhookError) return res.sendStatus(400);
    throw error;
  }

  res.sendStatus(204);   // answer first, then do the work

  if (event.type === 'batch.completed') {
    const job = event.data.object;   // same object as GET /batches/{id}
  }
});
import os
from flask import Flask, request
from namegender import webhooks, WebhookVerificationError

app = Flask(__name__)

@app.post("/namegender")
def namegender_webhook():
    try:
        event = webhooks.verify(
            request.get_data(),   # raw bytes, not request.json
            request.headers.get("NameGender-Signature"),
            os.environ["NAMEGENDER_WEBHOOK_SECRET"],
        )
    except WebhookVerificationError:
        return "", 400

    if event["type"] == "batch.completed":
        job = event["data"]["object"]   # same object as GET /batches/{id}
    return "", 204
<?php

$body   = file_get_contents('php://input');   // raw body, before json_decode
$header = $_SERVER['HTTP_NAMEGENDER_SIGNATURE'] ?? '';
$secret = getenv('NAMEGENDER_WEBHOOK_SECRET');

parse_str(str_replace(',', '&', $header), $parts);   // t=…&v1=…
preg_match_all('/v1=([0-9a-f]{64})/', $header, $m);

$t = (int) ($parts['t'] ?? 0);
$expected = hash_hmac('sha256', $t . '.' . $body, $secret);
$valid = abs(time() - $t) <= 300
    && array_filter($m[1], fn ($sig) => hash_equals($expected, $sig));

if (! $valid) {
    http_response_code(400);
    exit;
}

http_response_code(204);
$event = json_decode($body, true);
{
  "id": "evt_16f7c01502fda5436e8b7c4e",
  "type": "batch.completed",
  "created_at": "2026-09-24T10:04:12Z",
  "api_version": "v1",
  "data": {
    "object": {
      "id": "B-7K2M9QX4TA",
      "status": "completed",
      "rows": { "total": 200000, "processed": 200000, "identified": 187412 },
      "credits": { "reserved": 200000, "charged": 200000 },
      "result": { "url": "…/api/v1/batches/B-7K2M9QX4TA/result", "format": "csv" }
    }
  }
}
  • Répondez avec n'importe quel 2xx en moins de 10 secondes, puis faites le travail.
  • Toute autre réponse, redirection comprise, est réessayée jusqu'à 7 fois sur environ 45 heures. Si un point de terminaison échoue pendant trois jours, il est désactivé et vous recevez un e-mail.
  • Un nouvel essai porte le même identifiant et l'ordre n'est pas garanti. Dédupliquez sur NameGender-Event-Id et lisez la tâche par GET si vous avez besoin de son état actuel.
  • Renouveler le secret dans le tableau de bord laisse l'ancien signer pendant 24 heures : vous mettez votre serveur à jour sans manquer d'événement.
  • De nouveaux types d'événements peuvent s'ajouter. Répondez 2xx à un type que vous ne traitez pas et ignorez-le.
GET POST https://namegender.com/api/v1/gender/countries
Markdown

Répartition géographique

Retourne les pays dans lesquels un prénom est enregistré. Deux listes sont renvoyées et volontairement non fusionnées : `registrations` mesure le volume enregistré, comparable uniquement parmi les onze pays qui publient des statistiques de prénoms comptabilisées, et `attested_in` indique la présence, sans pondération.

Ceci n'est pas une inférence de pays d'origine ou d'ethnicité, et ne doit pas être utilisé comme telle. Les statistiques comptabilisées n'existent que pour onze pays : les États-Unis, le Royaume-Uni, la France, le Canada, l'Espagne, l'Irlande, la Norvège, l'Autriche, Israël, la Pologne et la Suisse. Une requête pour « Mehmet » classe donc la Suisse et la France en premier, à environ 29 % chacune, et la Turquie n'apparaît pas du tout dans le classement — la Turquie ne publie pas de chiffres. La Turquie apparaît cependant dans `attested_in`.
Paramètre Type Description
name
requis
string Le prénom à rechercher.
limit
optionnel
integer Nombre de pays comptabilisés à lister dans `registrations`. 1–100, par défaut 25. Les parts ne sont pas recalculées pour la liste raccourcie.
curl "https://namegender.com/api/v1/gender/countries?name=Mehmet" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "credits_charged": 1,
  "credits_remaining": 49994,
  "took_ms": 3,
  "name": "Mehmet",
  "basis": {
    "counted_sources": ["ssa", "ons", "nrs", "nisra", "insee", "statcan", "ine", "cso", "ssb", "statat", "pesel", "bfs"],
    "counted_countries": 8,
    "attested_countries": 16,
    "note": "Shares are calculated only across countries that publish counted name statistics…"
  },
  "registrations": [
    { "country": "CH", "count": 3890, "share": 29.45, "gender": "male", "source": "bfs"    },
    { "country": "FR", "count": 3775, "share": 28.58, "gender": "male", "source": "insee"  },
    { "country": "PL", "count": 1808, "share": 13.69, "gender": "male", "source": "pesel"  }
  ],
  "attested_in": ["AL","AT","AU","BE","CA","CH","ES","FR","GB","KS","MK","NO","PL","SE","TR","US"]
}

Un crédit par requête. `share` est calculé sur l'ensemble des pays comptabilisés et ne totalise donc 100 que si `limit` ne tronque pas la liste ; `counted_countries` compte lui aussi avant la troncature. `attested_in` ne contient pas de pourcentages car il n'y a pas de chiffres pour les calculer.

GET POST https://namegender.com/api/v1/salutation
Markdown

Formule d'appel

Transforme un nom en formule d'appel prête pour une lettre ou un e-mail, en dix langues : « Sehr geehrte Frau Dr. Müller, », « Sayın Ahmet Bey, », « Madame, », « 山田様 ». La détection du genre est incluse et coûte toujours un crédit. Chaque réponse contient une ligne formelle, une ligne informelle et une ligne neutre, ainsi que les éléments de la ligne formelle.

Paramètre Type Description
name
requis
string Nom complet, titres compris (« Dr. Anna Müller »). Envoyez ce champ ou `first_name` et `last_name`.
first_name, last_name
optionnel
string À utiliser à la place de `name` quand votre CRM range les noms dans des champs séparés. Aucune analyse n'est effectuée.
email
optionnel
string Adresse e-mail, utilisée quand aucun nom n’est envoyé. Le nom est lu dans la partie avant le @, sans accents (Mueller, pas Müller) ; info@ et les autres adresses de fonction reçoivent la formule pour les organisations.
language
optionnel
string Langue de la formule : en, en-US, en-GB, de, de-AT, de-CH, fr, es, it, pt, pt-PT, pt-BR, nl, tr, pl, ja. Sans ce paramètre : la langue de `locale`, puis la langue principale du pays, puis l'anglais. Une langue non prise en charge renvoie une erreur, jamais un passage silencieux à l'anglais.
country, locale, ip
optionnel
string Indice de pays pour la détection du genre, comme sur les endpoints de genre. Il ne détermine la langue que si `language` n'est pas envoyé.
gender
optionnel
string `male`, `female` ou `neutral`, si vous le connaissez déjà. Remplace la détection ; `neutral` donne toujours la forme neutre.
min_probability
optionnel
integer Probabilité minimale pour une formule genrée, 50–100. Par défaut 90.
title
optionnel
string Titre académique conservé dans un champ séparé, comme `Dr.` Utilisé dans les formules allemandes et anglaises.
curl -X POST "https://namegender.com/api/v1/salutation" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Dr. Anna Müller", "language": "de"}'
{
  "credits_charged": 1,
  "credits_remaining": 49993,
  "language": "de",
  "form": "gendered",
  "reason": null,
  "salutation": {
    "formal": "Sehr geehrte Frau Dr. Müller,",
    "informal": "Liebe Anna,",
    "neutral": "Guten Tag Dr. Anna Müller,"
  },
  "parts": { "opening": "Sehr geehrte", "courtesy": "Frau", "academic": "Dr.", "name": "Müller" },
  "gender": "female",
  "gender_source": "lookup",
  "probability": 99,
  "first_name": "Anna",
  "last_name": "Müller",
  "name_type": "personal"
}

Un genre erroné est pire que pas de genre du tout : la forme genrée n'est donc utilisée que si le genre est connu avec au moins `min_probability` et si la langue dispose de la partie du nom dont elle a besoin. Sinon, `form` vaut `neutral` et `reason` indique pourquoi. Les entreprises et les adresses de fonction reçoivent `form: organization`. `best_guess` et `ai_fallback` ne s'appliquent pas ici.

POST /api/v1/salutation/bulk accepte jusqu'à 100 noms dans `names`, un crédit chacun, avec les mêmes options appliquées à chaque nom.

GET POST https://namegender.com/api/v1/name-check
Markdown

Vérification du nom

Indique si un nom saisi dans un formulaire d'inscription ou de prospection ressemble au nom d'une vraie personne, et pourquoi. Il repère les frappes au hasard (« asdf qwerty »), les valeurs de remplissage (« Test Test », « John Doe », « n/a »), les personnages fictifs (« Mickey Mouse »), les grossièretés ainsi que les chiffres, symboles ou adresses e-mail dans le champ du nom. Un crédit par nom.

Ce n'est pas une vérification d'identité, et aucun nom n'est jamais qualifié de faux. Utilisez `implausible` et `suspicious` pour signaler une fiche ou demander plus d'informations, pas pour refuser automatiquement des personnes.
Paramètre Type Description
name
requis
string Le nom tel que saisi dans le formulaire. Envoyez ce champ ou `first_name` et `last_name`.
first_name, last_name
optionnel
string À utiliser à la place de `name` quand votre formulaire a des champs séparés.
country, locale, ip
optionnel
string Indice de pays, comme sur les endpoints de genre. Aide à découper le nom et à le rechercher dans les registres.
curl -X POST "https://namegender.com/api/v1/name-check" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "asdf qwerty"}'
{
  "credits_charged": 1,
  "credits_remaining": 49992,
  "query": "asdf qwerty",
  "assessment": "implausible",
  "score": 0,
  "signals": [
    { "code": "placeholder", "severity": "high", "part": "first_name", "value": "asdf" },
    { "code": "keyboard_pattern", "severity": "high", "part": "first_name", "value": "asdf" },
    { "code": "keyboard_pattern", "severity": "high", "part": "last_name", "value": "qwerty" }
  ],
  "first_name": "Asdf",
  "last_name": "Qwerty",
  "name_type": "personal",
  "evidence": { "first_name_status": "not_found", "first_name_counted_records": 0 }
}

`assessment` vaut `implausible` en présence d'un signal de gravité élevée (motif de clavier, lettres répétées, valeur de remplissage, grossièreté, e-mail ou URL), `suspicious` avec un signal moyen (personnage fictif, chiffres, symboles, nom d'entreprise, aucune voyelle, très long) ou deux faibles, et `plausible` sinon. `score` va de 0 à 100 pour votre propre seuil. Un prénom présent dans les registres officiels des naissances l'augmente ; un nom que nous n'avons jamais vu ne le baisse pas à lui seul. Les noms de famille sont jugés uniquement sur leur forme : aucun jeu de données de noms de famille n'est derrière cet endpoint.

Testé sur 4 610 vrais prénoms dans neuf écritures, seuls et associés à un nom de famille : aucun n'a été jugé suspect ou invraisemblable. Les noms de famille comme Null, Test ou Cockburn, les noms de deux lettres comme Ng et les noms uniques sont volontairement laissés tranquilles.

POST /api/v1/name-check/bulk accepte jusqu'à 100 noms dans `names`, un crédit chacun, avec un récapitulatif des trois évaluations.

GET POST https://namegender.com/api/v1/age
Markdown

Âge d'après le prénom

L'âge des personnes vivantes qui portent un prénom : l'âge médian, la moitié centrale (`age_range`) et les 80 % centraux (`age_range_80`). Brittany aux États-Unis : médiane 36 ans, la moitié entre 32 et 38 ans. Un crédit par nom.

Cela décrit un groupe, pas une personne. Pour la plupart des prénoms, la moitié centrale s'étend sur 10 à 25 ans. Utilisez-le pour l'analyse d'audience, la segmentation et la recherche, jamais pour décider quoi que ce soit au sujet d'une personne : crédit, embauche, logement, assurance, éligibilité ou contrôle d'âge.
Paramètre Type Description
name
requis
string Un prénom ou un nom complet ; c'est le prénom qui est utilisé.
gender
optionnel
string `male` ou `female` pour n'utiliser que les données de ce sexe. Les hommes prénommés Leslie ont 16 ans de plus que les femmes prénommées Leslie.
country, locale, ip
optionnel
string Indice de pays, comme sur les endpoints de genre. Couverts : US, FR et NO. Sans indice, la série des États-Unis est utilisée et `country_source` vaut `default`. Un autre pays renvoie `reason: country_not_covered` et ne coûte rien.
curl "https://namegender.com/api/v1/age?name=Brittany" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "credits_charged": 1,
  "credits_remaining": 49991,
  "request_id": "req_8f2c1a",
  "name": "Brittany",
  "first_name": "Brittany",
  "gender": null,
  "age": 36,
  "age_range": { "low": 32, "high": 38 },
  "age_range_80": { "low": 28, "high": 41 },
  "birth_year": 1990,
  "sample_size": 353775,
  "births": 361434,
  "country": "US",
  "country_source": "default",
  "source": "ssa",
  "series": "1880-2024",
  "reference_year": 2026,
  "reason": null
}

Méthode : naissances enregistrées par prénom, sexe et année, chaque année étant pondérée par la part de cette génération encore en vie (tables de mortalité par génération de la SSA). Sources : naissances SSA 1880–2024 (US), INSEE 1900–2025 (France), SSB 1945–2025 (Norvège). `reason` vaut `not_found` pour un prénom absent de la série et `insufficient_data` en dessous de 100 personnes vivantes.

Les naissances à l'étranger ne figurent dans aucune série : les prénoms courants chez les immigrés paraissent donc plus jeunes qu'ils ne le sont. La série norvégienne commence en 1945, les personnes nées avant manquent donc. La table de mortalité des États-Unis sert aussi pour la France et la Norvège.

POST /api/v1/age/bulk accepte jusqu'à 100 noms dans `names`, un crédit chacun, dans l'ordre d'envoi.

GET https://namegender.com/api/v1/me
Markdown

Solde

Consultez votre solde de crédits et ce qu'il reste de l'allocation gratuite du jour. Cet appel n'est pas facturé.

curl "https://namegender.com/api/v1/me" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "email": "you@example.com",
  "credits_remaining": 50099,
  "purchased_credits": 50000,
  "free_today": 99,
  "free_daily_limit": 100,
  "lifetime_requests": 12480
}

Scripts non-latins

Envoyez un prénom dans son propre script et nous le connectons aux données de référence. Aucun paramètre supplémentaire : nous détectons le script et sélectionnons la bonne stratégie pour celui-ci.

Supporté
Script arabe

L'écriture arabe omet les voyelles courtes, donc محمد se translittère en « mhmd » alors que nos données contiennent « muhammed ». Nous effectuons une correspondance sur la structure consonantique et conservons le marqueur féminin ة pour que خالد (Khalid) et خالدة (Khalida) restent distincts. Couvre également les prénoms persan et ourdou écrits en caractères arabes.

Caractères chinois

Convertis en Pinyin. Le nom de famille vient en premier en chinois, donc 李明 a pour nom 李 (Li) et pour prénom 明 (Ming) — nous retirons le nom de famille avant la recherche. Un seul caractère constitue un prénom complet et est traité comme un seul.

Coréen

Même gestion du nom de famille en premier qu'en chinois, en utilisant les noms de famille coréens courants.

Kana japonais

L'hiragana et le katakana sont lus correctement (ひろし → Hiroshi).

Cyrillique

Les prénoms russes, ukrainiens, bulgares et serbes se translittèrent directement.

Devanagari

Prénoms hindi, marathi et népalais. La voyelle finale inhérente est gérée (राहुल → Rahul, et non « Rahula »).

Non supporté
Kanji japonais

Les caractères kanji japonais et les caractères chinois occupent la même plage Unicode, nous ne pouvons donc pas les distinguer par les caractères seuls. L'entrée Han est lue comme du chinois : un nom kanji que nous ne possédons pas déjà textuellement reçoit sa lecture mandarine, ce qui pour un nom japonais est généralement incorrect (健太 se lit « jian tai » alors que le nom est Kenta). Les noms que nous possédons correspondent exactement et sont corrects. Envoyez les noms japonais en kana ou en caractères latins pour être sûr.

Thaï

Le thaï omet les voyelles comme l'arabe et nécessite sa propre couche de correspondance. Pas encore implémenté, donc ces requêtes retournent null.

# Arap yazısı — ünsüz iskeleti üzerinden eşleşir
curl "https://namegender.com/api/v1/gender?name=%D9%85%D8%AD%D9%85%D8%AF" -H "Authorization: Bearer KEY"
# -> { "gender": "male", "probability": 100, "source": "script", "matched_as": "mahamad" }

# Çince — soyadı ayıklanır, verilen ad sorgulanır
curl "https://namegender.com/api/v1/gender?name=%E6%9D%8E%E6%98%8E" -H "Authorization: Bearer KEY"
# -> { "gender": "male", "probability": 92, "source": "db" }

Échec de la copie. Sélectionnez et copiez le texte.

Quand nous ne pouvons pas du tout convertir un script, la réponse est gender: null avec source: none. Vérifiez le champ source : script signifie que nous avons translittéré, db signifie que nous avons fait correspondre directement les caractères que vous avez envoyés. Les deux ont des niveaux de confiance différents, et nous vous montrons lequel vous avez obtenu.

Champs de la réponse

Identiques sur tous les endpoints.

Champ Type Description
credits_charged integer Nombre de crédits déduits pour cet appel.
credits_remaining integer Votre solde utilisable une fois cet appel payé : crédits achetés plus ce qu'il reste de l'allocation gratuite du jour.
query string L'entrée exactement telle que vous l'avez envoyée, avant tout nettoyage.
name string Le nom que nous avons réellement recherché après suppression des titres et noms de famille.
first_name string Prénom extrait de l'entrée. Renvoyé même si gender est null, sans coût supplémentaire.
middle_name string Autres prénoms entre le prénom et le nom de famille. Les initiales sont ignorées.
last_name string Nom de famille, particules comprises (van, de la). Toujours null pour les noms d'utilisateur.
name_type string personal, organization (Acme SARL) ou role (info@, service client). Les organisations et les rôles n'obtiennent pas de genre.
gender string male, female, ou null si nous ne sommes pas suffisamment confiants pour nous prononcer.
country string Le pays d'où proviennent les statistiques, ou null pour l'agrégat mondial.
country_source string Origine du pays : country, locale, ip, ou null quand la réponse est mondiale.
sample_size integer Nombre de personnes enregistrées derrière cette réponse. 0 signifie que la source publie des proportions ou des attestations, pas un décompte que nous pouvons vérifier.
probability integer Confiance dans le genre indiqué, de 50 à 100. 0 quand genre est null.
took_ms integer Temps passé à résoudre la recherche, en millisecondes entières. Le temps réseau de votre côté n'est pas inclus.

Deux champs que les autres services ne vous proposent pas

source indique d'où provient la réponse : la base de données de référence, une correspondance approchée, ou la solution de secours IA. matched_as nomme l'entrée sur laquelle la correspondance approchée a abouti. Ensemble, ils vous permettent de décider à quel point faire confiance à un résultat plutôt que de l'accepter aveuglément.

Champ Type Description
source string db, script, fuzzy, llm, ou none.
confidence string élevée, moyenne, basse, non vérifiée ou inconnue, selon la preuve d'échantillon.
matched_as string Pour une correspondance approchée, l'entrée de la base de données qui a correspondu. Sinon null.

Codes d'erreur

Le code de statut HTTP vous indique qu'un appel a échoué. Le corps JSON nomme ensuite la raison dans error, l'explique dans message, et fournit un request_id à communiquer au support ainsi qu'un lien vers la ligne correspondante ci-dessous. Basez votre logique sur error, jamais sur message : les messages sont traduits et peuvent être reformulés.

Code HTTP Signification
missing_key 401 Aucune clé API n'a été envoyée. Ajoutez un header Authorization: Bearer ou un header X-Api-Key à la requête.
invalid_key 401 Cette clé API n'est pas valide.
revoked_key 401 Cette clé API a été révoquée.
blocked 403 Ce compte a été suspendu. Contactez le support.
email_not_verified 403 L'adresse e-mail de ce compte n'a pas encore été confirmée. Ouvrez le lien de confirmation que nous vous avons envoyé, ou demandez-en un nouveau depuis votre tableau de bord.
ip_not_allowed 403 Les requêtes de cette adresse IP ne sont pas autorisées pour cette clé.
proxy_secret_required 403 Cette clé ne fonctionne que via sa place de marché API, qui signe chaque requête. Utilisez la clé qui vous a été émise là-bas.
forbidden 403 Vous n'êtes pas autorisé à effectuer cette action.
no_credits 402 Vous n'avez plus de crédits. Achetez-en ou attendez la réinitialisation de votre quota gratuit quotidien.
missing_input 400 Le paramètre « name » est obligatoire.
invalid_input 422 Le paramètre « name » n'est pas valide.
too_many_items 422 Un maximum de 100 éléments peuvent être envoyés dans une seule requête.
unknown_endpoint 404 Il n'existe pas d'endpoint à ce chemin. Vérifiez l'URL dans la documentation de l'API.
method_not_allowed 405 Cet endpoint n'accepte pas les requêtes DELETE.
payload_too_large 413 Le corps de la requête est trop volumineux.
rate_limited 429 Trop de requêtes. Ralentissez et réessayez dans un instant.
batch_not_found 404 Aucune tâche de fichier ne porte cet identifiant sur ce compte.
batch_not_startable 409 Cette tâche a déjà été lancée ou clôturée.
batch_not_finished 409 Cette tâche n'est pas encore terminée. Vérifiez son statut et téléchargez le résultat une fois qu'elle est terminée.
batch_in_progress 409 Cette tâche est en cours de traitement et ne peut pas être annulée maintenant. Supprimez-la une fois terminée.
result_gone 410 Cette tâche n'a aucun résultat à télécharger. Elle a échoué, a été annulée, a expiré, ou son résultat à téléchargement unique a déjà été récupéré.
too_many_batches 429 Vous avez déjà 100 tâches de fichier en cours. Attendez qu'une se termine avant d'en lancer une autre.
not_ready 503 La base de données de noms est en reconstruction. Réessayez dans un moment.
server_error 500 Une erreur est survenue de notre côté. Nous avons été notifiés.
{
  "error": "no_credits",
  "message": "You are out of credits. Buy more or wait for your daily free quota to reset.",
  "request_id": "req_9c1f5b2a7e0d4a13",
  "docs": "https://namegender.com/docs#error-no_credits"
}

Échec de la copie. Sélectionnez et copiez le texte.

Limites de débit

L'utilisation normale ne déclenche pas de limite. La limite existe pour empêcher qu'une clé compromise soit abusée, et elle s'applique par clé API plutôt que par IP afin que plusieurs clients sur un même serveur ne consomment pas l'allocation les uns des autres.

Limite actuelle : 1 200 requêtes par minute par clé. Besoin de plus ? Demandez et nous l'augmenterons sur votre compte.

Chaque réponse porte les en-têtes standards X-RateLimit-Limit et X-RateLimit-Remaining.

Espaces et lettres non latines dans les requêtes GET

Un nom comme Ayşe Yılmaz ou 中村 ne peut pas circuler tel quel dans une URL. Encodez la valeur en pourcentage lorsque vous appelez en GET, ou envoyez-la dans un corps JSON en POST et passez-vous totalement d'encodage.

Ayşe Yılmaz  ->  Ay%C5%9Fe%20Y%C4%B1lmaz
محمد          ->  %D9%85%D8%AD%D9%85%D8%AF
中村           ->  %E4%B8%AD%E6%9D%91

Échec de la copie. Sélectionnez et copiez le texte.