Referencia de REST API
Unos pocos endpoints, una estructura de respuesta. Todo lo siguiente está activo en tu cuenta.
https://namegender.com/api/v1/gender
Registrarse gratis
Markdown para asistentes de código como Claude Code, Cursor y Copilot. Pégalo en el chat o dale el enlace al asistente.
Inicio rápido
Crea una clave en tu panel de control y envía tu primera solicitud. No necesitas 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
Cada endpoint devuelve la misma estructura, así que puedes cambiar entradas sin modificar tu código de análisis.
Autenticación
Cada solicitud lleva tu clave de API en un encabezado. Usa Authorization: Bearer por defecto, o X-Api-Key si tu cliente HTTP reserva el encabezado Authorization para otra cosa. Una clave colocada en la URL se rechaza: las URL acaban copiadas en registros de proxy, herramientas de analítica y el historial del navegador.
Authorization: Bearer ng_live_xxxxxxxxxxxx
No se pudo copiar. Selecciona y copia el texto.
X-Api-Key: ng_live_xxxxxxxxxxxx
No se pudo copiar. Selecciona y copia el texto.
Puedes restringir una clave a direcciones IP específicas desde el panel de control.
Bibliotecas cliente
Envolturas delgadas sobre la API REST. Envían tu clave, construyen cada petición y convierten las respuestas de error en excepciones.
npm install namegender
No se pudo copiar. Selecciona y copia el texto.
npm install -g namegender
No se pudo copiar. Selecciona y copia el texto.
composer require namegender/namegender
No se pudo copiar. Selecciona y copia el texto.
pip install namegender-client
No se pudo copiar. Selecciona y copia el texto.
gem install namegender
No se pudo copiar. Selecciona y copia el texto.
<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>
No se pudo copiar. Selecciona y copia el texto.
dotnet add package NameGender --version 0.6.0
No se pudo copiar. Selecciona y copia el texto.
go get github.com/anpekesen/namegender-go@v0.7.0
No se pudo copiar. Selecciona y copia el texto.
remotes::install_github('anpekesen/namegender-r', ref = 'v0.7.0')
No se pudo copiar. Selecciona y copia el texto.
Install-Module NameGender
No se pudo copiar. Selecciona y copia el texto.
cargo add namegender
No se pudo copiar. Selecciona y copia el texto.
No las necesitas. La API son unos pocos endpoints de JSON simple; una biblioteca te ahorra una tarde, no un proyecto. Si tu lenguaje no está listado, la referencia REST tiene ejemplos para copiar y pegar.
Ver todoAsistentes de IA (MCP)
Usa NameGender desde Claude, Cursor y cualquier otro cliente compatible con el Model Context Protocol. Pregúntale al asistente por una lista de nombres y llamará a la API por ti, con la evidencia junto a cada respuesta.
claude mcp add namegender -e NAMEGENDER_API_KEY=ng_live_... -- npx -y namegender-mcp
No se pudo copiar. Selecciona y copia el texto.
{
"mcpServers": {
"namegender": {
"command": "npx",
"args": [
"-y",
"namegender-mcp"
],
"env": {
"NAMEGENDER_API_KEY": "ng_live_..."
}
}
}
}
No se pudo copiar. Selecciona y copia el texto.
Añade esto al archivo de configuración MCP del cliente y reinícialo.
Herramientas
gender_from_name- Género a partir de un nombre de pila o un nombre completo.
gender_from_email- Lee el nombre de una dirección de email; las direcciones genéricas como info@ devuelven desconocido.
gender_from_username- Lee el nombre de un nombre de usuario o handle.
gender_bulk- Hasta 100 valores en una sola solicitud, con un resumen de la tasa de coincidencia.
name_countries- Países donde un nombre está registrado. No es una afirmación sobre su origen.
salutation- Saludo inicial de una carta en el idioma de la carta; la forma neutra cuando el género no es seguro.
name_check- Si un nombre escrito en un formulario parece real, con los motivos. Nunca califica un nombre de falso.
age_from_name- Edad mediana y rangos de edad de las personas con un nombre de pila en Estados Unidos, Francia y Noruega.
account_status- Créditos restantes y la asignación gratuita de hoy.
Cada consulta usa créditos de la cuenta propietaria de la clave, exactamente igual que una llamada directa a la API. Publicado en el registro oficial de MCP como io.github.anpekesen/namegender. Paquete npm · Código fuente
Género a partir del nombre
Acepta un nombre de pila o un nombre completo. Los títulos, nombres intermedios y apellidos se eliminan antes de la búsqueda, así que "Dr. Ayşe Yılmaz" y "Ayşe" dan la misma respuesta.
| Parámetro | Tipo | Descripción |
|---|---|---|
name
requerido
|
string
|
El nombre a clasificar. Nombre de pila o nombre completo. |
country
opcional
|
string
|
Código de país ISO 3166-1 alfa-2. Mejora la precisión para nombres cuyo género varía según la región, como Andrea (masculino en Italia, femenino en Alemania). |
locale
opcional
|
string
|
Una etiqueta de idioma como de-DE o en_US, por ejemplo el idioma del navegador. Su región pasa a ser el país cuando no se envía country. Una etiqueta sin región (en, de) no fija ningún país. |
ip
opcional
|
string
|
La dirección IP del usuario final. Se usa su país cuando no se envía country ni un locale con región. No se guarda. IP geolocation by DB-IP (db-ip.com). |
ai_fallback
opcional
|
boolean
|
Si el nombre no tiene entrada en nuestros datos, pide una estimación a un modelo de lenguaje en lugar de devolver null. Solo funciona cuando las búsquedas con IA están activadas en tu configuración, y cuesta un crédito adicional. |
best_guess
opcional
|
boolean
|
Devuelve el género predominante incluso cuando la evidencia no alcanza el umbral de confianza. Desactivado por defecto: una respuesta cercana al 50/50 que parece definitiva hace más daño que 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
}
Género a partir del correo electrónico
Extrae la persona de la parte local de la dirección y luego la clasifica. "ayse.yilmaz84@example.com" se resuelve a Ayşe.
| Parámetro | Tipo | Descripción |
|---|---|---|
email
requerido
|
string
|
La dirección de correo electrónico. Solo se usa la parte anterior a @. |
country
opcional
|
string
|
Código de país ISO 3166-1 alfa-2. Mejora la precisión para nombres cuyo género varía según la región, como Andrea (masculino en Italia, femenino en Alemania). |
locale
opcional
|
string
|
Una etiqueta de idioma como de-DE o en_US, por ejemplo el idioma del navegador. Su región pasa a ser el país cuando no se envía country. Una etiqueta sin región (en, de) no fija ningún país. |
ip
opcional
|
string
|
La dirección IP del usuario final. Se usa su país cuando no se envía country ni un locale con región. No se guarda. IP geolocation by DB-IP (db-ip.com). |
ai_fallback
opcional
|
boolean
|
Si el nombre no tiene entrada en nuestros datos, pide una estimación a un modelo de lenguaje en lugar de devolver null. Solo funciona cuando las búsquedas con IA están activadas en tu configuración, y cuesta un crédito adicional. |
best_guess
opcional
|
boolean
|
Devuelve el género predominante incluso cuando la evidencia no alcanza el umbral de confianza. Desactivado por defecto: una respuesta cercana al 50/50 que parece definitiva hace más daño que un null. |
best_guess actúa sobre el nombre leído de la dirección, no sobre la dirección en sí. Si no se puede leer ningún nombre, no hay nada que forzar y gender sigue siendo null. Ten en cuenta que aquí una respuesta forzada se apoya en una extracción que también puede ser errónea.
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"
}
Género a partir del nombre de usuario
Maneja camelCase, snake_case, dígitos finales y signos @ iniciales. "AyseYilmaz84" se resuelve a Ayşe.
| Parámetro | Tipo | Descripción |
|---|---|---|
username
requerido
|
string
|
El nombre de usuario o identificador. Un @ inicial se ignora. |
country
opcional
|
string
|
Código de país ISO 3166-1 alfa-2. Mejora la precisión para nombres cuyo género varía según la región, como Andrea (masculino en Italia, femenino en Alemania). |
locale
opcional
|
string
|
Una etiqueta de idioma como de-DE o en_US, por ejemplo el idioma del navegador. Su región pasa a ser el país cuando no se envía country. Una etiqueta sin región (en, de) no fija ningún país. |
ip
opcional
|
string
|
La dirección IP del usuario final. Se usa su país cuando no se envía country ni un locale con región. No se guarda. IP geolocation by DB-IP (db-ip.com). |
ai_fallback
opcional
|
boolean
|
Si el nombre no tiene entrada en nuestros datos, pide una estimación a un modelo de lenguaje en lugar de devolver null. Solo funciona cuando las búsquedas con IA están activadas en tu configuración, y cuesta un crédito adicional. |
best_guess
opcional
|
boolean
|
Devuelve el género predominante incluso cuando la evidencia no alcanza el umbral de confianza. Desactivado por defecto: una respuesta cercana al 50/50 que parece definitiva hace más daño que 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"
}
Solicitud en lote
Envía hasta 100 nombres en una solicitud. Usa esto en lugar de hacer un bucle: una llamada en lote para 100 nombres es un único viaje de ida y vuelta y una búsqueda deduplicada única.
| Parámetro | Tipo | Descripción |
|---|---|---|
names
requerido
|
string[]
|
Array de nombres. Máximo 100 elementos. |
type
opcional
|
string
|
Qué son los elementos: nombre, correo electrónico o nombre de usuario. Por defecto, nombre. |
country
opcional
|
string
|
Se aplica a cada elemento de la solicitud. |
locale
opcional
|
string
|
Etiqueta de idioma cuya región pasa a ser el país de cada elemento cuando no se envía country. |
ip
opcional
|
string
|
Dirección IP del usuario final cuyo país se usa para cada elemento cuando no se envía country ni un locale con región. No se guarda. 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" }
]
}
Los resultados vuelven en el mismo orden en que los enviaste. Los créditos se cobran por nombre, y toda la solicitud se rechaza antes de cualquier trabajo si tu saldo es insuficiente, así que nunca obtendrás un lote procesado parcialmente.
El bloque de resumen te muestra la tasa de coincidencia de un vistazo, para que puedas decidir si la entrada necesita limpieza antes de procesar el resto.
Trabajos de archivo
Sube un archivo CSV o XLSX de hasta 100 MB y 1.000.000 filas y recíbelo con columnas de género añadidas a cada fila. Un crédito por fila, cobrado solo si el trabajo se completa.
-
1.
POST /batchesEnvía el archivo y name_column. El trabajo se pone en cola de inmediato. -
2.
GET /batches/{id}Consulta el trabajo hasta que status sea completed o failed. poll_after_seconds indica cuánto esperar entre consultas. -
3.
GET /batches/{id}/resultDescarga el resultado. Vuelve en el formato que subiste.
| Parámetro | Tipo | Descripción |
|---|---|---|
file
requerido
|
file
|
CSV, TSV o XLSX con una fila de encabezado. |
name_column
requerido
|
string
|
Encabezado de la columna con los nombres, tal como aparece en el archivo. Obligatorio salvo con start=false. |
country_column
opcional
|
string
|
Encabezado de una columna con un código de país por fila. |
country
opcional
|
string
|
País predeterminado para las filas que no tienen uno. |
ai_fallback
opcional
|
boolean
|
Consultar un modelo de IA para nombres que no están en el conjunto de datos. Requiere el consentimiento de IA en Ajustes. |
best_guess
opcional
|
boolean
|
Devolver el género más probable aunque la evidencia sea débil. |
delete_after_download
opcional
|
boolean
|
El resultado se puede descargar una vez y después se elimina. |
start
opcional
|
boolean
|
false: solo subir e inspeccionar. Por defecto, 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 es obligatorio para iniciar: una columna adivinada que resulte incorrecta gastaría créditos en los datos equivocados. Envía start=false para ver primero las columnas, una vista previa y el coste, y luego inicia el trabajo.
Envía una cabecera Idempotency-Key. Un reintento con la misma clave devuelve el primer trabajo en lugar de abrir otro.
Puede haber hasta 3 trabajos en cola o en ejecución a la vez. Un trabajo que no ha empezado se puede cancelar y se devuelve su crédito; uno en proceso no se puede detener.
Webhooks
Añade un endpoint en Webhooks de tu panel y le enviaremos un POST firmado cuando un trabajo de archivo termine o falle, sin que tengas que consultar.
| Evento | Tipo | Descripción |
|---|---|---|
batch.completed
|
BatchJob
|
El trabajo terminó. El cuerpo lleva el trabajo tal como lo devuelve GET /batches/{id}. |
batch.failed
|
BatchJob
|
El trabajo falló y no se cobró. Ramifica según error.code. |
credits.low
|
CreditsAlert
|
Al ritmo actual, los créditos duran 7 días o menos. Se comprueba cada hora; se tienen en cuenta las renovaciones de suscripción. |
credits.depleted
|
CreditsAlert
|
El saldo está vacío y las peticiones se rechazan con 402. Se comprueba cada hora. |
webhook.test
|
object
|
Solo se envía con "Enviar evento de prueba" del panel y solo a ese endpoint. |
| Cabecera | Tipo | Descripción |
|---|---|---|
NameGender-Signature
requerido
|
string
|
t=<segundos unix>,v1=<hex>. Tras renovar el secreto aparece un segundo v1 durante 24 horas. |
NameGender-Event-Id
requerido
|
string
|
El id del evento. Es el mismo en cada reintento del mismo evento. |
NameGender-Delivery-Attempt
requerido
|
integer
|
1 en el primer intento, hasta 8. |
Verifica cada petición
v1 es el HMAC-SHA256 de la marca de tiempo, un punto y el cuerpo sin procesar, con el secreto de tu endpoint. Compara en tiempo constante, acepta la petición si coincide algún v1 y rechaza una marca de tiempo que difiera más de cinco minutos de tu reloj. Las bibliotecas cliente hacen todo esto en una llamada.
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" }
}
}
}
- Responde con cualquier 2xx en menos de 10 segundos y haz el trabajo después.
- Cualquier otra respuesta, redirecciones incluidas, se reintenta hasta 7 veces durante unas 45 horas. Si un endpoint sigue fallando tres días, se desactiva y te enviamos un correo.
- Un reintento lleva el mismo id y el orden no está garantizado. Deduplica por NameGender-Event-Id y lee el trabajo con GET cuando necesites su estado actual.
- Al renovar el secreto en el panel, el anterior sigue firmando 24 horas, así actualizas tu servidor sin perder eventos.
- Pueden añadirse nuevos tipos de evento. Responde 2xx a un tipo que no gestiones e ignóralo.
Distribución por país
Devuelve los países donde se registra un nombre. Se devuelven dos listas que deliberadamente no se fusionan: `registrations` es el volumen medido, comparable solo entre los once países que publican estadísticas de nombres contabilizadas, y `attested_in` es presencia, sin ponderación asignada.
| Parámetro | Tipo | Descripción |
|---|---|---|
name
requerido
|
string
|
El nombre a buscar. |
limit
opcional
|
integer
|
Cuántos países contabilizados incluir en `registrations`. 1–100, predeterminado 25. Los porcentajes no se recalculan para la lista más 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 crédito por solicitud. `share` se calcula sobre todos los países con conteo, así que suma 100 solo cuando `limit` no recorta la lista; `counted_countries` también cuenta antes del recorte. `attested_in` no incluye porcentajes porque no hay conteo detrás de esos registros para calcularlo.
Saludo
Convierte un nombre en un saludo listo para una carta o un correo, en diez idiomas: “Sehr geehrte Frau Dr. Müller,”, “Sayın Ahmet Bey,”, “Madame,”, “山田様”. La consulta de género está incluida y cuesta el mismo crédito. Cada respuesta trae una línea formal, una informal y una neutra, además de las partes de la línea formal.
| Parámetro | Tipo | Descripción |
|---|---|---|
name
requerido
|
string
|
Nombre completo, con títulos incluidos (“Dr. Anna Müller”). Envía este o `first_name` y `last_name`. |
first_name, last_name
opcional
|
string
|
Úsalos en lugar de `name` cuando tu CRM guarda los nombres en campos separados. No se analiza nada. |
email
opcional
|
string
|
Dirección de correo, usada cuando no se envía un nombre. El nombre se lee de la parte antes de la @, sin tildes (Mueller, no Müller); info@ y otras direcciones de cargo reciben el saludo para organizaciones. |
language
opcional
|
string
|
Idioma del saludo: en, en-US, en-GB, de, de-AT, de-CH, fr, es, it, pt, pt-PT, pt-BR, nl, tr, pl, ja. Sin él: el idioma de `locale`, luego el idioma principal del país y luego inglés. Un idioma no admitido es un error, nunca un cambio silencioso a inglés. |
country, locale, ip
opcional
|
string
|
Pista de país para la consulta de género, como en los endpoints de género. Solo elige el idioma cuando no se envía `language`. |
gender
opcional
|
string
|
`male`, `female` o `neutral`, si ya lo conoces. Reemplaza la consulta; `neutral` siempre da la forma neutra. |
min_probability
opcional
|
integer
|
Probabilidad mínima para un saludo con género, 50–100. Predeterminado 90. |
title
opcional
|
string
|
Título académico guardado en un campo aparte, como `Dr.` Se usa en los saludos en alemán e inglés. |
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 género equivocado es peor que ninguno, así que la forma con género solo se usa cuando el género se conoce con al menos `min_probability` y el idioma tiene la parte del nombre que necesita. Si no, `form` es `neutral` y `reason` explica por qué. Las empresas y las direcciones de cargo reciben `form: organization`. `best_guess` y `ai_fallback` no se aplican aquí.
POST /api/v1/salutation/bulk acepta hasta 100 nombres en `names`, un crédito cada uno, con las mismas opciones aplicadas a cada nombre.
Comprobación de nombre
Indica si un nombre escrito en un formulario de registro o de captación parece el nombre de una persona real, y por qué. Detecta tecleo al azar (“asdf qwerty”), valores de relleno (“Test Test”, “John Doe”, “n/a”), personajes de ficción (“Mickey Mouse”), groserías y dígitos, símbolos o direcciones de correo en el campo del nombre. Un crédito por nombre.
| Parámetro | Tipo | Descripción |
|---|---|---|
name
requerido
|
string
|
El nombre tal como se escribió en el formulario. Envía este o `first_name` y `last_name`. |
first_name, last_name
opcional
|
string
|
Úsalos en lugar de `name` cuando tu formulario tiene campos separados. |
country, locale, ip
opcional
|
string
|
Pista de país, como en los endpoints de género. Ayuda a separar el nombre y a buscarlo en los registros. |
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` es `implausible` cuando hay una señal de gravedad alta (patrón de teclado, letras repetidas, valor de relleno, grosería, correo o URL), `suspicious` con una media (personaje de ficción, dígitos, símbolos, nombre de empresa, sin vocales, muy largo) o dos bajas, y `plausible` en los demás casos. `score` va de 0 a 100 para que fijes tu propio umbral. Un nombre de pila que aparece en registros oficiales de nacimientos lo sube; un nombre que nunca hemos visto no lo baja por sí solo. Los apellidos se juzgan solo por su forma: detrás de este endpoint no hay un conjunto de datos de apellidos.
Probado con 4.610 nombres de pila reales en nueve escrituras, solos y junto a un apellido: ninguno se marcó como sospechoso o inverosímil. Los apellidos como Null, Test o Cockburn, los nombres de dos letras como Ng y los nombres únicos se dejan en paz a propósito.
POST /api/v1/name-check/bulk acepta hasta 100 nombres en `names`, un crédito cada uno, con un resumen de las tres valoraciones.
Edad por nombre
Qué edad tienen las personas vivas con un nombre de pila: la edad mediana, la mitad central (`age_range`) y el 80% central (`age_range_80`). Brittany en Estados Unidos: mediana 36, la mitad entre 32 y 38. Un crédito por nombre.
| Parámetro | Tipo | Descripción |
|---|---|---|
name
requerido
|
string
|
Un nombre de pila o un nombre completo; se usa el nombre de pila. |
gender
opcional
|
string
|
`male` o `female` para usar solo los registros de ese sexo. Los hombres llamados Leslie tienen 16 años más que las mujeres llamadas Leslie. |
country, locale, ip
opcional
|
string
|
Pista de país, como en los endpoints de género. Cubiertos: US, FR y NO. Sin pista se usa la serie de Estados Unidos y `country_source` es `default`. Otro país devuelve `reason: country_not_covered` y no cuesta nada. |
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étodo: nacimientos registrados por nombre, sexo y año, con cada año ponderado por la proporción de esa cohorte de nacimiento que sigue viva (tablas de mortalidad por cohorte de la SSA). Fuentes: nacimientos SSA 1880–2024 (US), INSEE 1900–2025 (Francia), SSB 1945–2025 (Noruega). `reason` es `not_found` para un nombre que no está en la serie e `insufficient_data` por debajo de 100 personas vivas.
Los nacimientos en el extranjero no están en ninguna serie, así que los nombres comunes entre inmigrantes parecen más jóvenes de lo que son. La serie de Noruega empieza en 1945, por lo que faltan las personas nacidas antes. La tabla de mortalidad de Estados Unidos se usa también para Francia y Noruega.
POST /api/v1/age/bulk acepta hasta 100 nombres en `names`, un crédito cada uno, en el orden de envío.
Saldo
Consulta tu saldo de créditos y lo que queda de la asignación gratuita de hoy. Esta llamada no se cobra.
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
}
Escrituras no latinas
Envía un nombre en su escritura original y lo vinculamos con los datos de referencia. Sin parámetros adicionales: detectamos la escritura y elegimos la estrategia correcta.
La escritura árabe omite las vocales cortas, así que محمد se translittera a "mhmd" mientras nuestros datos contienen "muhammed". Hacemos coincidencia por el patrón de consonantes, y preservamos el marcador femenino ة para que خالد (Khalid) y خالدة (Khalida) se mantengan separados. También cubre nombres persas y urdu escritos en árabe.
Se convierten a pinyin. El apellido viene primero en chino, así que 李明 tiene apellido 李 (Li) y nombre 明 (Ming) — removemos el apellido antes de buscar. Un carácter único es un nombre completo y se trata como tal.
Mismo tratamiento de apellido primero que en chino, usando los apellidos coreanos comunes.
Hiragana y katakana se leen correctamente (ひろし → Hiroshi).
Nombres rusos, ucranianos, búlgaros y serbios se transliteran directamente.
Nombres en hindi, marathi y nepalí. Se maneja la vocal final inherente (राहुल → Rahul, no "Rahula").
Los caracteres kanji japoneses y los caracteres chinos ocupan el mismo rango Unicode, por lo que no podemos distinguirlos solo por los caracteres. La entrada Han se lee como chino: un nombre kanji que no tenemos almacenado literalmente obtiene su lectura mandarina, que para un nombre japonés generalmente es incorrecta (健太 se lee como "jian tai" cuando el nombre es Kenta). Los nombres que sí tenemos coinciden exactamente y son correctos. Envía nombres japoneses en kana o caracteres latinos para estar seguro.
El tailandés omite vocales como el árabe y necesita su propia capa de coincidencia. Aún no está implementado, así que estos devuelven 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" }
No se pudo copiar. Selecciona y copia el texto.
Cuando no podemos convertir un sistema de escritura, la respuesta es gender: null con source: none. Verifica el campo source: script significa que transliteramos, db significa que coincidimos directamente con los caracteres que enviaste. Los dos tienen diferentes niveles de confianza, y te mostramos cuál obtuviste.
Campos de respuesta
Idénticos en todos los endpoints.
| Campo | Tipo | Descripción |
|---|---|---|
credits_charged
|
integer
|
Cuántos créditos se descontaron por esta llamada. |
credits_remaining
|
integer
|
Tu saldo disponible una vez pagada esta llamada: créditos comprados más lo que queda de la asignación gratuita de hoy. |
query
|
string
|
La entrada exactamente como la enviaste, antes de cualquier limpieza. |
name
|
string
|
El nombre que realmente buscamos después de eliminar títulos y apellidos. |
first_name
|
string
|
Nombre de pila extraído de la entrada. Se devuelve aunque gender sea null, sin coste adicional. |
middle_name
|
string
|
Otros nombres entre el nombre de pila y el apellido. Las iniciales se omiten. |
last_name
|
string
|
Apellido, con partículas como van o de la. Con un country hispanohablante incluye los dos apellidos. Siempre null en nombres de usuario. |
name_type
|
string
|
personal, organization (Acme S.L.) o role (info@, atención al cliente). Las organizaciones y los roles no reciben género. |
gender
|
string
|
masculino, femenino, o null cuando no tenemos suficiente confianza. |
country
|
string
|
El país del que provienen las estadísticas, o null para el agregado global. |
country_source
|
string
|
De dónde salió el país: country, locale, ip o null cuando la respuesta es mundial. |
sample_size
|
integer
|
Número de personas registradas detrás de esta respuesta. 0 significa que la fuente publica proporciones o constancias, no un recuento que podamos auditar. |
probability
|
integer
|
Confianza en el género indicado, 50 a 100. 0 cuando el género es null. |
took_ms
|
integer
|
Tiempo que dedicamos a resolver la búsqueda, en milisegundos enteros. No incluye el tiempo de red de tu lado. |
Dos campos que otros servicios no ofrecen
source te dice de dónde vino la respuesta: la base de datos de referencia, una coincidencia aproximada o el fallback de IA. matched_as nombra la entrada en la que aterrizó la coincidencia aproximada. Juntos te permiten decidir cuánto confiar en un resultado individual en lugar de aceptarlo sin cuestionarlo.
| Campo | Tipo | Descripción |
|---|---|---|
source
|
string
|
db, script, fuzzy, llm, o none. |
confidence
|
string
|
alta, media, baja, sin verificar o desconocida, según la evidencia de la muestra. |
matched_as
|
string
|
Para una coincidencia aproximada, la entrada de la base de datos que coincidió. En caso contrario null. |
Códigos de error
El código de estado HTTP te indica que una llamada falló. Después, el cuerpo JSON nombra el motivo en error, lo explica en message y te da un request_id para citar al soporte, además de un enlace a la fila correspondiente más abajo. Decide siempre según error, nunca según message: los mensajes se traducen y pueden redactarse de otra forma.
| Código | HTTP | Significado |
|---|---|---|
missing_key |
401 | No se envió ninguna clave API. Añade un header Authorization: Bearer o un header X-Api-Key a la solicitud. |
invalid_key |
401 | Esta clave API no es válida. |
revoked_key |
401 | Esta clave API ha sido revocada. |
blocked |
403 | Esta cuenta ha sido suspendida. Contacta con soporte. |
email_not_verified |
403 | La dirección de correo de esta cuenta aún no se ha confirmado. Abre el enlace de confirmación que te enviamos o solicita uno nuevo desde tu panel. |
ip_not_allowed |
403 | Las solicitudes desde esta dirección IP no están permitidas para esta clave. |
proxy_secret_required |
403 | Esta clave solo funciona a través de su marketplace de API, que firma cada solicitud. Usa la clave que te emitieron allí. |
forbidden |
403 | No tienes permiso para realizar esta acción. |
no_credits |
402 | No tienes créditos disponibles. Compra más o espera a que se reinicie tu cuota gratuita diaria. |
missing_input |
400 | El parámetro "name" es obligatorio. |
invalid_input |
422 | El parámetro "name" no es válido. |
too_many_items |
422 | Se puede enviar un máximo de 100 elementos en una solicitud. |
ai_consent_required |
422 | ai_fallback envía el nombre a un proveedor de IA de terceros, al cual esta cuenta no ha dado su consentimiento. Consulta el campo "ai" para ver quién es ese proveedor y luego habilita las búsquedas de IA en la configuración de tu dashboard. |
unknown_endpoint |
404 | No hay endpoint en esta ruta. Verifica la URL en la documentación de la API. |
method_not_allowed |
405 | Este endpoint no acepta solicitudes DELETE. |
payload_too_large |
413 | El cuerpo de la solicitud es demasiado grande. |
rate_limited |
429 | Demasiadas solicitudes. Ralentiza el ritmo e intenta de nuevo en poco tiempo. |
batch_not_found |
404 | No hay ningún trabajo de archivo con este ID en esta cuenta. |
batch_not_startable |
409 | Este trabajo ya se ha iniciado o cerrado. |
batch_not_finished |
409 | Este trabajo aún no ha terminado. Consulta su estado y descarga el resultado cuando se haya completado. |
batch_in_progress |
409 | Este trabajo se está procesando y no se puede cancelar ahora. Elimínalo cuando haya terminado. |
result_gone |
410 | Este trabajo no tiene resultado para descargar. Falló, se canceló, caducó o su resultado de descarga única ya se descargó. |
too_many_batches |
429 | Ya tienes 100 trabajos de archivo en curso. Espera a que termine uno antes de iniciar otro. |
not_ready |
503 | La base de datos de nombres se está reconstruyendo. Intenta de nuevo en un momento. |
server_error |
500 | Algo salió mal en nuestro lado. Ya hemos sido notificados. |
{
"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"
}
No se pudo copiar. Selecciona y copia el texto.
Límites de velocidad
El uso normal no alcanza un límite. El tope existe para evitar que una clave filtrada sea abusada, y se cuenta por clave API en lugar de por IP para que varios clientes en un servidor no consuman la asignación de otros.
Límite actual: 1.200 solicitudes por minuto por clave. ¿Necesitas más? Pregunta y lo aumentaremos en tu cuenta.
Cada respuesta lleva los headers estándar X-RateLimit-Limit y X-RateLimit-Remaining.
Espacios y letras no latinas en solicitudes GET
Un nombre como Ayşe Yılmaz o 中村 no puede viajar en una URL tal como se escribe. Aplica codificación porcentual al valor cuando llames con GET, o envíalo en un cuerpo JSON con POST y olvídate de codificar.
Ayşe Yılmaz -> Ay%C5%9Fe%20Y%C4%B1lmaz
محمد -> %D9%85%D8%AD%D9%85%D8%AF
中村 -> %E4%B8%AD%E6%9D%91
No se pudo copiar. Selecciona y copia el texto.