Continua → Panoramica

Riferimento REST API

Pochi endpoint, una struttura di risposta. Tutto sotto è attivo sul tuo account.

https://namegender.com/api/v1/gender Registrati gratis
llms-full.txt

Markdown per assistenti di programmazione come Claude Code, Cursor e Copilot. Incollalo nella chat o passa il link all'assistente.

Avvio rapido

Crea una chiave nella tua dashboard, poi invia la tua prima richiesta. Non è necessario alcun SDK.

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

Ogni endpoint restituisce la stessa struttura, quindi puoi cambiare input senza modificare il codice di parsing.

Autenticazione

Ogni richiesta invia la tua chiave API in un'intestazione. Usa Authorization: Bearer come impostazione predefinita, oppure X-Api-Key quando il tuo client HTTP riserva l'intestazione Authorization ad altro. Una chiave inserita nell'URL viene rifiutata: gli URL vengono copiati nei log dei proxy, negli strumenti di analisi e nella cronologia del browser.

Intestazione Authorization (consigliato)
Authorization: Bearer ng_live_xxxxxxxxxxxx

Copia non riuscita. Seleziona e copia il testo.

Intestazione X-Api-Key
X-Api-Key: ng_live_xxxxxxxxxxxx

Copia non riuscita. Seleziona e copia il testo.

Non esporre mai la tua chiave nel codice lato client. Le chiamate da un browser o app mobile devono passare attraverso il tuo backend.

Puoi limitare una chiave a indirizzi IP specifici dalla dashboard.

Librerie client

Wrapper sottili sull'API REST. Inviano la tua chiave, costruiscono ogni richiesta e trasformano le risposte di errore in eccezioni.

JavaScript Sorgente
npm install namegender

Copia non riuscita. Seleziona e copia il testo.

Command line Sorgente
npm install -g namegender

Copia non riuscita. Seleziona e copia il testo.

composer require namegender/namegender

Copia non riuscita. Seleziona e copia il testo.

Python Sorgente
pip install namegender-client

Copia non riuscita. Seleziona e copia il testo.

gem install namegender

Copia non riuscita. Seleziona e copia il testo.

<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>

Copia non riuscita. Seleziona e copia il testo.

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

Copia non riuscita. Seleziona e copia il testo.

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

Copia non riuscita. Seleziona e copia il testo.

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

Copia non riuscita. Seleziona e copia il testo.

PowerShell Sorgente
Install-Module NameGender

Copia non riuscita. Seleziona e copia il testo.

cargo add namegender

Copia non riuscita. Seleziona e copia il testo.

Non ti serve. L'API è una manciata di semplici endpoint JSON; una libreria ti fa risparmiare un pomeriggio, non un progetto. Se il tuo linguaggio non è elencato, il riferimento REST contiene esempi pronti da copiare.

Visualizza tutto

Assistenti IA (MCP)

Usa NameGender da Claude, Cursor e qualsiasi altro client che supporta il Model Context Protocol. Chiedi all'assistente di una lista di nomi e chiamerà l'API per te, con le evidenze accanto a ogni risposta.

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

Copia non riuscita. Seleziona e copia il testo.

Claude Desktop, Cursor e altri client
{
    "mcpServers": {
        "namegender": {
            "command": "npx",
            "args": [
                "-y",
                "namegender-mcp"
            ],
            "env": {
                "NAMEGENDER_API_KEY": "ng_live_..."
            }
        }
    }
}

Copia non riuscita. Seleziona e copia il testo.

Aggiungi questo al file di configurazione MCP del client e riavvialo.

Strumenti

gender_from_name
Genere da un nome di battesimo o da un nome completo.
gender_from_email
Legge il nome in un indirizzo email; gli indirizzi generici come info@ restituiscono sconosciuto.
gender_from_username
Legge il nome in uno username o handle.
gender_bulk
Fino a 100 valori in una sola richiesta, con un riepilogo del tasso di corrispondenza.
name_countries
Paesi in cui un nome è registrato. Non è un'affermazione sull'origine.
salutation
Formula di saluto di una lettera nella lingua della lettera; la forma neutra quando il genere non è certo.
name_check
Se un nome digitato in un modulo sembra reale, con i motivi. Non definisce mai falso un nome.
age_from_name
Età mediana e fasce d'età delle persone con un nome di battesimo negli Stati Uniti, in Francia e in Norvegia.
account_status
Crediti rimanenti e quota gratuita di oggi.

Ogni ricerca usa i crediti dell'account a cui appartiene la chiave, esattamente come una chiamata diretta all'API. Presente nel registro ufficiale MCP come io.github.anpekesen/namegender. Pacchetto npm · Sorgente

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

Genere da nome

Accetta un nome o un nome completo. I titoli, i nomi centrali e i cognomi vengono eliminati prima della ricerca, quindi "Dr. Ayşe Yılmaz" e "Ayşe" danno la stessa risposta.

Parametro Tipo Descrizione
name
obbligatorio
string Il nome da classificare. Nome o nome completo.
country
facoltativo
string Codice paese ISO 3166-1 alpha-2. Migliora l'accuratezza per i nomi il cui genere varia per regione, come Andrea (maschile in Italia, femminile in Germania).
locale
facoltativo
string Un tag di lingua come de-DE o en_US, ad esempio la lingua del browser. La sua regione diventa il paese quando country non viene inviato. Un tag senza regione (en, de) non imposta alcun paese.
ip
facoltativo
string L'indirizzo IP dell'utente finale. Il suo paese viene usato quando non si invia né country né un locale con regione. Non viene memorizzato. IP geolocation by DB-IP (db-ip.com).
ai_fallback
facoltativo
boolean Se il nome non ha una voce nei nostri dati, chiedi una stima a un modello linguistico invece di restituire null. Funziona solo dopo aver attivato le ricerche AI nelle impostazioni e costa un credito aggiuntivo.
best_guess
facoltativo
boolean Restituisci il genere prevalente anche quando le prove non raggiungono la soglia di confidenza. Disattivato per impostazione predefinita: una risposta quasi 50/50 che sembra definitiva fa più danni di 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

Genere da email

Estrae la persona dalla parte locale dell'indirizzo, poi classifica quella. "ayse.yilmaz84@example.com" si risolve in Ayşe.

Parametro Tipo Descrizione
email
obbligatorio
string L'indirizzo email. Viene utilizzata solo la parte prima di @.
country
facoltativo
string Codice paese ISO 3166-1 alpha-2. Migliora l'accuratezza per i nomi il cui genere varia per regione, come Andrea (maschile in Italia, femminile in Germania).
locale
facoltativo
string Un tag di lingua come de-DE o en_US, ad esempio la lingua del browser. La sua regione diventa il paese quando country non viene inviato. Un tag senza regione (en, de) non imposta alcun paese.
ip
facoltativo
string L'indirizzo IP dell'utente finale. Il suo paese viene usato quando non si invia né country né un locale con regione. Non viene memorizzato. IP geolocation by DB-IP (db-ip.com).
ai_fallback
facoltativo
boolean Se il nome non ha una voce nei nostri dati, chiedi una stima a un modello linguistico invece di restituire null. Funziona solo dopo aver attivato le ricerche AI nelle impostazioni e costa un credito aggiuntivo.
best_guess
facoltativo
boolean Restituisci il genere prevalente anche quando le prove non raggiungono la soglia di confidenza. Disattivato per impostazione predefinita: una risposta quasi 50/50 che sembra definitiva fa più danni di un null.

best_guess agisce sul nome proprio ricavato dall'indirizzo, non sull'indirizzo stesso. Se non si riesce a ricavare un nome, non c'è nulla da forzare e gender resta null. Tieni presente che una risposta forzata qui poggia su un'estrazione che può essere a sua volta sbagliata.

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

Genere da username

Gestisce camelCase, snake_case, cifre finali e segni @ iniziali. "AyseYilmaz84" si risolve in Ayşe.

Parametro Tipo Descrizione
username
obbligatorio
string Lo username o handle. Un @ iniziale viene ignorato.
country
facoltativo
string Codice paese ISO 3166-1 alpha-2. Migliora l'accuratezza per i nomi il cui genere varia per regione, come Andrea (maschile in Italia, femminile in Germania).
locale
facoltativo
string Un tag di lingua come de-DE o en_US, ad esempio la lingua del browser. La sua regione diventa il paese quando country non viene inviato. Un tag senza regione (en, de) non imposta alcun paese.
ip
facoltativo
string L'indirizzo IP dell'utente finale. Il suo paese viene usato quando non si invia né country né un locale con regione. Non viene memorizzato. IP geolocation by DB-IP (db-ip.com).
ai_fallback
facoltativo
boolean Se il nome non ha una voce nei nostri dati, chiedi una stima a un modello linguistico invece di restituire null. Funziona solo dopo aver attivato le ricerche AI nelle impostazioni e costa un credito aggiuntivo.
best_guess
facoltativo
boolean Restituisci il genere prevalente anche quando le prove non raggiungono la soglia di confidenza. Disattivato per impostazione predefinita: una risposta quasi 50/50 che sembra definitiva fa più danni di 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

Richiesta in blocco

Invia fino a 100 nomi in una richiesta. Usa questo invece di fare un ciclo: una chiamata in blocco per 100 nomi è un singolo round trip e una singola ricerca deduplicata.

Parametro Tipo Descrizione
names
obbligatorio
string[] Array di nomi. Massimo 100 elementi.
type
facoltativo
string Cosa sono gli elementi: nome, email o username. Predefinito su nome.
country
facoltativo
string Applicato a ogni elemento nella richiesta.
locale
facoltativo
string Tag di lingua la cui regione diventa il paese di ogni elemento quando country non viene inviato.
ip
facoltativo
string Indirizzo IP dell'utente finale il cui paese vale per ogni elemento quando non si invia né country né un locale con regione. Non viene memorizzato. 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" }
  ]
}

I risultati tornano nello stesso ordine in cui li hai inviati. I crediti vengono addebitati per nome e l'intera richiesta viene rifiutata prima di qualsiasi operazione se il tuo saldo è insufficiente, quindi non avrai mai un batch parzialmente elaborato.

Il blocco di riepilogo ti mostra il tasso di corrispondenza a colpo d'occhio, così puoi decidere se l'input ha bisogno di pulizia prima di elaborare il resto.

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

Lavori su file

Carica un file CSV o XLSX fino a 100 MB e 1.000.000 righe e ricevilo con le colonne del genere aggiunte a ogni riga. Un credito per riga, addebitato solo se il lavoro viene completato.

  1. 1. POST /batches Invia il file e name_column. Il lavoro viene messo subito in coda.
  2. 2. GET /batches/{id} Leggi il lavoro finché status non è completed o failed. poll_after_seconds indica quanto attendere tra una lettura e l'altra.
  3. 3. GET /batches/{id}/result Scarica il risultato. Torna nel formato caricato.
Parametro Tipo Descrizione
file
obbligatorio
file CSV, TSV o XLSX con una riga di intestazione.
name_column
obbligatorio
string Intestazione della colonna con i nomi, esattamente come nel file. Obbligatorio tranne con start=false.
country_column
facoltativo
string Intestazione di una colonna con un codice paese per riga.
country
facoltativo
string Paese predefinito per le righe che non ne hanno uno.
ai_fallback
facoltativo
boolean Chiedere a un modello di IA i nomi non presenti nel dataset. Richiede il consenso all'IA nelle Impostazioni.
best_guess
facoltativo
boolean Restituire il genere più probabile anche quando le prove sono deboli.
delete_after_download
facoltativo
boolean Il risultato può essere scaricato una sola volta, poi viene eliminato.
start
facoltativo
boolean false: solo caricare e ispezionare. Predefinito true.
# 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 è obbligatorio per avviare: una colonna indovinata che si rivela sbagliata spenderebbe crediti sui dati sbagliati. Invia start=false per vedere prima le colonne, un'anteprima e il costo, poi avvia il lavoro.

Invia un'intestazione Idempotency-Key. Un nuovo tentativo con la stessa chiave restituisce il primo lavoro invece di aprirne un secondo.

Fino a 3 lavori possono essere in coda o in esecuzione contemporaneamente. Un lavoro non avviato può essere annullato e il suo credito viene restituito; un lavoro in elaborazione non può essere fermato.

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

Webhook

Aggiungi un endpoint in Webhook nella dashboard e gli invieremo un POST firmato quando un lavoro su file termina o non riesce, senza bisogno di interrogare lo stato.

Evento Tipo Descrizione
batch.completed BatchJob Il lavoro è terminato. Il corpo contiene il lavoro esattamente come lo restituisce GET /batches/{id}.
batch.failed BatchJob Il lavoro non è riuscito e non è stato addebitato. Decidi in base a error.code.
credits.low CreditsAlert Al ritmo attuale i crediti durano 7 giorni o meno. Controllato ogni ora; i rinnovi dell'abbonamento sono considerati.
credits.depleted CreditsAlert Il saldo è esaurito e le richieste vengono rifiutate con 402. Controllato ogni ora.
webhook.test object Inviato solo da "Invia evento di prova" nella dashboard e solo a quell'endpoint.
Intestazione Tipo Descrizione
NameGender-Signature
obbligatorio
string t=<secondi unix>,v1=<hex>. Dopo il rinnovo del segreto compare un secondo v1 per 24 ore.
NameGender-Event-Id
obbligatorio
string L'id dell'evento. È lo stesso a ogni nuovo tentativo dello stesso evento.
NameGender-Delivery-Attempt
obbligatorio
integer 1 al primo tentativo, fino a 8.

Verifica ogni richiesta

v1 è l'HMAC-SHA256 del timestamp, di un punto e del corpo grezzo, con il segreto del tuo endpoint. Confronta in tempo costante, accetta la richiesta se corrisponde un qualsiasi v1 e rifiuta un timestamp distante più di cinque minuti dal tuo orologio. Le librerie client fanno tutto questo in una chiamata.

Verifica il corpo così come arriva. Un framework che interpreta il JSON e lo serializza di nuovo cambia i byte e la firma non corrisponde.
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" }
    }
  }
}
  • Rispondi con un qualsiasi 2xx entro 10 secondi, poi esegui il lavoro.
  • Qualsiasi altra risposta, reindirizzamenti compresi, viene ritentata fino a 7 volte in circa 45 ore. Se un endpoint continua a non rispondere per tre giorni viene disattivato e ricevi un'e-mail.
  • Un nuovo tentativo porta lo stesso id e l'ordine non è garantito. Elimina i duplicati con NameGender-Event-Id e leggi il lavoro con GET quando ti serve lo stato attuale.
  • Rinnovando il segreto dalla dashboard, il vecchio continua a firmare per 24 ore: aggiorni il server senza perdere eventi.
  • Possono aggiungersi nuovi tipi di evento. Rispondi 2xx a un tipo che non gestisci e ignoralo.
GET POST https://namegender.com/api/v1/gender/countries
Markdown

Distribuzione geografica

Restituisce i paesi in cui un nome è registrato. Vengono restituite due liste deliberatamente non unite: `registrations` misura il volume registrato, comparabile solo tra gli undici paesi che pubblicano statistiche ufficiali sui nomi, e `attested_in` indica la presenza, senza alcun peso.

Questo non è un'inferenza di paese d'origine o etnia e non deve essere utilizzato come tale. Le statistiche ufficiali esistono solo per undici paesi: USA, Regno Unito, Francia, Canada, Spagna, Irlanda, Norvegia, Austria, Israele, Polonia e Svizzera. Una ricerca di "Mehmet" quindi posiziona al primo posto la Svizzera e la Francia, con circa il 29% ciascuna, e la Turchia non appare affatto in classifica — la Turchia non pubblica conteggi. La Turchia appare invece in `attested_in`.
Parametro Tipo Descrizione
name
obbligatorio
string Il nome da cercare.
limit
facoltativo
integer Quanti paesi con conteggi ufficiali elencare in `registrations`. 1–100, predefinito 25. Le quote non vengono ricalcolate per la lista più corta.
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 credito per richiesta. `share` è calcolato su tutti i paesi con conteggi ufficiali, quindi somma a 100 solo quando `limit` non taglia la lista; anche `counted_countries` conta prima del taglio. `attested_in` non contiene percentuali perché non esiste un conteggio sottostante da cui calcolarle.

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

Formula di saluto

Trasforma un nome in una formula di saluto pronta per una lettera o un'email, in dieci lingue: “Sehr geehrte Frau Dr. Müller,”, “Sayın Ahmet Bey,”, “Madame,”, “山田様”. La ricerca del genere è inclusa e costa lo stesso credito. Ogni risposta contiene una riga formale, una informale e una neutra, più le parti della riga formale.

Parametro Tipo Descrizione
name
obbligatorio
string Nome completo, titoli inclusi (“Dr. Anna Müller”). Invia questo oppure `first_name` e `last_name`.
first_name, last_name
facoltativo
string Usali al posto di `name` quando il tuo CRM tiene i nomi in campi separati. Non viene analizzato nulla.
email
facoltativo
string Indirizzo email, usato quando non viene inviato un nome. Il nome si legge dalla parte prima della @, senza accenti (Mueller, non Müller); info@ e gli altri indirizzi di funzione ricevono la formula per le organizzazioni.
language
facoltativo
string Lingua della formula: en, en-US, en-GB, de, de-AT, de-CH, fr, es, it, pt, pt-PT, pt-BR, nl, tr, pl, ja. Senza: la lingua di `locale`, poi la lingua principale del paese, poi l'inglese. Una lingua non supportata è un errore, mai un passaggio silenzioso all'inglese.
country, locale, ip
facoltativo
string Indicazione del paese per la ricerca del genere, come negli endpoint di genere. Sceglie la lingua solo quando `language` non viene inviato.
gender
facoltativo
string `male`, `female` o `neutral`, se lo conosci già. Sostituisce la ricerca; `neutral` dà sempre la forma neutra.
min_probability
facoltativo
integer Probabilità minima per una formula con genere, 50–100. Predefinito 90.
title
facoltativo
string Titolo accademico tenuto in un campo separato, come `Dr.` Usato nelle formule in tedesco e in inglese.
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 genere sbagliato è peggio di nessuno, quindi la forma con genere viene usata solo quando il genere è noto con almeno `min_probability` e la lingua ha la parte del nome che le serve. Altrimenti `form` è `neutral` e `reason` spiega il motivo. Aziende e indirizzi di ruolo ricevono `form: organization`. `best_guess` e `ai_fallback` qui non si applicano.

POST /api/v1/salutation/bulk accetta fino a 100 nomi in `names`, un credito ciascuno, con le stesse opzioni applicate a ogni nome.

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

Controllo del nome

Dice se un nome digitato in un modulo di registrazione o di contatto sembra il nome di una persona reale, e perché. Individua la digitazione a caso sulla tastiera (“asdf qwerty”), i segnaposto (“Test Test”, “John Doe”, “n/a”), i personaggi di fantasia (“Mickey Mouse”), le volgarità e cifre, simboli o indirizzi email nel campo del nome. Un credito per nome.

Non è una verifica dell'identità e non definisce mai falso un nome. Usa `implausible` e `suspicious` per segnalare un record o chiedere più informazioni, non per rifiutare automaticamente le persone.
Parametro Tipo Descrizione
name
obbligatorio
string Il nome così come è stato digitato nel modulo. Invia questo oppure `first_name` e `last_name`.
first_name, last_name
facoltativo
string Usali al posto di `name` quando il tuo modulo ha campi separati.
country, locale, ip
facoltativo
string Indicazione del paese, come negli endpoint di genere. Aiuta a scomporre il nome e a cercarlo nei registri.
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` è `implausible` quando c'è un segnale di gravità alta (sequenza di tastiera, lettere ripetute, segnaposto, volgarità, email o URL), `suspicious` con uno medio (personaggio di fantasia, cifre, simboli, nome di azienda, nessuna vocale, molto lungo) o due bassi, e `plausible` negli altri casi. `score` va da 0 a 100 per la tua soglia. Un nome di battesimo presente nei registri ufficiali delle nascite lo alza; un nome che non abbiamo mai visto non lo abbassa da solo. I cognomi sono giudicati solo dalla loro forma: dietro questo endpoint non c'è alcun dataset di cognomi.

Testato su 4.610 nomi di battesimo reali in nove sistemi di scrittura, da soli e abbinati a un cognome: nessuno è stato segnato come sospetto o non plausibile. Cognomi come Null, Test o Cockburn, nomi di due lettere come Ng e nomi singoli vengono lasciati stare di proposito.

POST /api/v1/name-check/bulk accetta fino a 100 nomi in `names`, un credito ciascuno, con un riepilogo delle tre valutazioni.

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

Età dal nome

Quanti anni hanno le persone in vita con un certo nome di battesimo: l'età mediana, la metà centrale (`age_range`) e l'80% centrale (`age_range_80`). Brittany negli Stati Uniti: mediana 36, metà tra 32 e 38. Un credito per nome.

Descrive un gruppo, non una persona. Per la maggior parte dei nomi la metà centrale copre da 10 a 25 anni. Usalo per analisi del pubblico, segmenti e ricerca, mai per decidere qualcosa su una singola persona: credito, assunzioni, alloggio, assicurazioni, idoneità o verifiche dell'età.
Parametro Tipo Descrizione
name
obbligatorio
string Un nome di battesimo o un nome completo; viene usato il nome di battesimo.
gender
facoltativo
string `male` o `female` per usare solo i dati di quel sesso. Gli uomini di nome Leslie hanno 16 anni più delle donne di nome Leslie.
country, locale, ip
facoltativo
string Indicazione del paese, come negli endpoint di genere. Coperti: US, FR e NO. Senza indicazione si usa la serie degli Stati Uniti e `country_source` è `default`. Un altro paese restituisce `reason: country_not_covered` e non costa nulla.
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
}

Metodo: nascite registrate per nome, sesso e anno, con ogni anno pesato per la quota di quella coorte di nascita ancora in vita (tavole di mortalità per coorte della SSA). Fonti: nascite SSA 1880–2024 (US), INSEE 1900–2025 (Francia), SSB 1945–2025 (Norvegia). `reason` è `not_found` per un nome assente dalla serie e `insufficient_data` sotto le 100 persone in vita.

Le nascite all'estero non sono in nessuna serie, quindi i nomi diffusi tra gli immigrati sembrano più giovani di quanto siano. La serie norvegese inizia nel 1945, quindi mancano le persone nate prima. La tavola di mortalità degli Stati Uniti viene usata anche per Francia e Norvegia.

POST /api/v1/age/bulk accetta fino a 100 nomi in `names`, un credito ciascuno, nell'ordine di invio.

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

Saldo

Leggi il tuo saldo crediti e quanto resta della quota gratuita di oggi. Questa chiamata non viene addebitata.

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
}

Script non latini

Invia un nome nel suo script originale e lo colleghiamo ai dati di riferimento. Nessun parametro aggiuntivo: rilieviamo lo script e scegliamo la strategia giusta.

Supportato
Script arabo

La scrittura araba omette le vocali brevi, quindi محمد si traslittera in "mhmd" mentre i nostri dati contengono "muhammed". Facciamo un match sullo schema consonantico e conserviamo il marker femminile ة, così خالد (Khalid) e خالدة (Khalida) rimangono distinti. Copre anche i nomi persiani e urdu scritti in script arabo.

Caratteri cinesi

Convertiti in Pinyin. Il cognome viene per primo in cinese, quindi 李明 ha cognome 李 (Li) e nome proprio 明 (Ming) — rimuoviamo il cognome prima della ricerca. Un singolo carattere è un nome proprio completo e viene trattato come uno.

Coreano

Stesso trattamento cognome-primo del cinese, usando i cognomi coreani comuni.

Kana giapponese

Hiragana e katakana vengono letti correttamente (ひろし → Hiroshi).

Cirillico

I nomi russo, ucraino, bulgaro e serbo si traslitterano direttamente.

Devanagari

Nomi hindi, marathi e nepalese. La vocale finale intrinseca è gestita (राहुल → Rahul, non "Rahula").

Non supportato
Kanji giapponese

I caratteri kanji giapponesi e i caratteri cinesi occupano lo stesso intervallo Unicode, quindi non possiamo distinguerli dai caratteri stessi. L'input Han viene letto come cinese: un nome kanji che non possediamo esattamente viene traslitterato secondo la pronuncia mandarino, che per un nome giapponese è solitamente errata (健太 viene letto come "jian tai" quando il nome è Kenta). I nomi che possediamo corrispondono esattamente e sono corretti. Invia i nomi giapponesi in kana o caratteri latini per essere sicuro.

Thai

Il thai omette le vocali come l'arabo e ha bisogno del suo strato di matching. Non ancora implementato, quindi questi restituiscono 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" }

Copia non riuscita. Seleziona e copia il testo.

Quando non riusciamo a convertire uno script, la risposta è gender: null con source: none. Controlla il campo source: script significa che abbiamo traslitterato, db significa che abbiamo trovato una corrispondenza esatta con i caratteri che hai inviato. I due hanno un livello di confidence diverso e ti mostriamo quale hai ottenuto.

Campi della risposta

Identici su tutti gli endpoint.

Campo Tipo Descrizione
credits_charged integer Quanti crediti sono stati scalati per questa chiamata.
credits_remaining integer Il tuo saldo spendibile una volta pagata questa chiamata: crediti acquistati più quanto resta della quota gratuita di oggi.
query string L'input esattamente come l'hai inviato, prima di qualsiasi pulizia.
name string Il nome che abbiamo effettivamente cercato dopo aver rimosso titoli e cognomi.
first_name string Nome proprio estratto dall'input. Restituito anche quando gender è null, senza costi aggiuntivi.
middle_name string Altri nomi tra il nome proprio e il cognome. Le iniziali vengono scartate.
last_name string Cognome, comprese particelle come van o de la. Sempre null per i nomi utente.
name_type string personal, organization (Acme S.r.l.) o role (info@, servizio clienti). Organizzazioni e ruoli non ricevono un genere.
gender string male, female, o null quando non siamo abbastanza sicuri.
country string Il paese da cui provengono le statistiche, o null per l'aggregato globale.
country_source string Da dove viene il paese: country, locale, ip o null quando la risposta è mondiale.
sample_size integer Numero di persone registrate dietro questa risposta. 0 significa che la fonte pubblica proporzioni o attestazioni, non un conteggio che possiamo verificare.
probability integer Confidenza nel genere indicato, da 50 a 100. 0 quando gender è null.
took_ms integer Tempo impiegato per risolvere la ricerca, in millisecondi interi. Il tempo di rete dal tuo lato non è incluso.

Due campi che altri servizi non forniscono

source ti dice da dove proviene la risposta: dal database di riferimento, da una corrispondenza fuzzy o dal fallback AI. matched_as indica il nome su cui la corrispondenza fuzzy ha trovato un match. Insieme ti permettono di decidere quanto fidarti di un singolo risultato invece di accettarlo per scontato.

Campo Tipo Descrizione
source string db, script, fuzzy, llm, o none.
confidence string alta, media, bassa, non verificata o sconosciuta, in base alle prove campionarie.
matched_as string Per una corrispondenza fuzzy, il record del database che ha trovato un match. Altrimenti null.

Codici di errore

Il codice di stato HTTP ti dice che una chiamata non è riuscita. Il corpo JSON indica poi il motivo in error, lo spiega in message e ti fornisce un request_id da citare al supporto, più un link alla riga corrispondente della documentazione qui sotto. Basa la logica su error, mai su message: i messaggi sono tradotti e possono essere riformulati.

Codice HTTP Significato
missing_key 401 Nessuna chiave API inviata. Aggiungi alla richiesta un header Authorization: Bearer o un header X-Api-Key.
invalid_key 401 Questa chiave API non è valida.
revoked_key 401 Questa chiave API è stata revocata.
blocked 403 Questo account è stato sospeso. Contatta il supporto.
email_not_verified 403 L'indirizzo e-mail di questo account non è ancora stato confermato. Apri il link di conferma che ti abbiamo inviato oppure richiedine uno nuovo dalla dashboard.
ip_not_allowed 403 Le richieste da questo indirizzo IP non sono consentite per questa chiave.
proxy_secret_required 403 Questa chiave funziona solo tramite il suo marketplace API, che firma ogni richiesta. Utilizza la chiave che ti è stata rilasciata lì.
forbidden 403 Non sei autorizzato a eseguire questa azione.
no_credits 402 Non hai più crediti. Acquistane altri o attendi il reset della tua quota gratuita giornaliera.
missing_input 400 Il parametro "name" è obbligatorio.
invalid_input 422 Il parametro "name" non è valido.
too_many_items 422 Un massimo di 100 elementi può essere inviato in una richiesta.
unknown_endpoint 404 Non esiste alcun endpoint a questo percorso. Verifica l'URL nella documentazione dell'API.
method_not_allowed 405 Questo endpoint non accetta richieste DELETE.
payload_too_large 413 Il corpo della richiesta è troppo grande.
rate_limited 429 Troppe richieste. Rallenta e riprova tra poco.
batch_not_found 404 Non esiste alcun lavoro su file con questo ID in questo account.
batch_not_startable 409 Questo lavoro è già stato avviato o chiuso.
batch_not_finished 409 Questo lavoro non è ancora terminato. Controlla lo stato e scarica il risultato quando è completato.
batch_in_progress 409 Questo lavoro è in elaborazione e non può essere annullato ora. Eliminalo quando è terminato.
result_gone 410 Questo lavoro non ha un risultato da scaricare. Non è riuscito, è stato annullato, è scaduto oppure il suo risultato a download singolo è già stato scaricato.
too_many_batches 429 Hai già 100 lavori su file in corso. Attendi che uno termini prima di avviarne un altro.
not_ready 503 Il database dei nomi è in fase di ricostruzione. Riprova tra un momento.
server_error 500 Qualcosa è andato storto. Siamo stati notificati.
{
  "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"
}

Copia non riuscita. Seleziona e copia il testo.

Limiti di velocità

L'uso normale non raggiunge un limite. Il limite esiste per evitare che una chiave compromessa venga abusata, e si conta per chiave API anziché per IP in modo che più clienti su un server non consumino l'allowance gli uni degli altri.

Limite attuale: 1.200 richieste al minuto per chiave. Hai bisogno di più? Contattaci e lo aumenteremo sul tuo account.

Ogni risposta include gli header standard X-RateLimit-Limit e X-RateLimit-Remaining.

Spazi e lettere non latine nelle richieste GET

Un nome come Ayşe Yılmaz o 中村 non può viaggiare in un URL così come è scritto. Codifica il valore con il percent-encoding quando chiami con GET, oppure invialo in un corpo JSON con POST e salta del tutto la codifica.

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

Copia non riuscita. Seleziona e copia il testo.