namegender / namegender
Official PHP client for the NameGender API
Requires
- php: ^8.1
Requires (Dev)
- phpunit/phpunit: ^10.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
PHP client for the NameGender API. Requires PHP 8.1 or later. Get an API key from the namegender.com dashboard.
composer require namegender/namegender
$client = new NameGender\Client($_ENV['NAMEGENDER_API_KEY']); $result = $client->name('Ayşe', country: 'TR'); echo $result['gender'], ' ', $result['probability'], ' ', $result['sample_size'];
Options and response
name, email, username and bulk take an $options array with
ai_fallback and best_guess:
$result = $client->name('Andrea', country: 'IT', options: ['best_guess' => true]);
A result carries query, name, first_name, middle_name, last_name, name_type, gender, country, probability,
sample_size, took_ms, source, confidence and matched_as, alongside
credits_charged, credits_remaining, data_version and request_id.
Success is the HTTP status: any non-2xx response throws
NameGender\NameGenderException with status and body
(['error', 'message', 'request_id', 'docs']). Branch on body['error'], not
on the message.
Country distribution
Returns the countries a name is recorded in. This is not a country-of-origin or ethnicity inference, and must not be used as one.
$result = $client->countries('Mehmet', limit: 10); print_r($result['registrations']); // [['country' => 'FR', 'count' => 3775, 'share' => 58.97, 'gender' => 'male', 'probability' => 99, 'source' => 'insee'], ...] print_r($result['attested_in']); // ['AL', 'AU', 'BE', ..., 'TR', 'US'] echo $result['basis']['note'];
The two lists are deliberately kept apart. registrations is measured volume and
is comparable only among the seven countries that publish counted birth
statistics (US, UK, France, Canada, Spain, Ireland, Norway); share is a
percentage across those counts alone. attested_in is presence with no weight
attached, which is where countries that publish no counts, such as Turkey, Japan
and India, appear. Show basis.note next to any percentage you display.
limit (1–100, default 25) caps how many counted countries come back in
registrations. One credit per request.
File jobs
Upload a CSV or XLSX file (up to 100 MB and 1,000,000 rows) and get it back with gender columns added. One credit per row, charged only if the job completes.
$batches = $client->batches(); $job = $batches->create('customers.csv', [ // a path, the file's contents (with 'filename') or a stream 'name_column' => 'first_name', // required to start 'country_column' => 'country', // optional: a country code per row ]); $done = $batches->wait($job['id'], onProgress: fn (array $j) => print($j['progress']."\n")); if ($done['status'] === 'failed') { throw new RuntimeException($done['error']['code']); } $batches->download($done['id'], 'customers-gender.csv');
name_column is required to start: a guessed column that turns out to be
wrong would spend credits on the wrong data. To see the columns and the cost
first, upload with 'start' => false, read $job['inspection'], then call
$batches->start($job['id'], ['name_column' => ...]).
create sends an Idempotency-Key and retries network errors and 502/503/504
with the same key, so a retry never opens a second job. Pass your own
idempotency_key to keep that guarantee across your own retries.
create and download give up only after a transfer stalls for 300 seconds
(other calls: 30); pass 'timeout' => ... to create, or timeout: to
download, to change that.
wait returns a failed job rather than throwing; branch on
$job['error']['code']. cancel returns the credit of a job that has not
started, and deletes a finished one. list(limit:, page:) includes jobs
started from the dashboard. Up to three jobs can be queued or running at once;
a fourth is refused with 429 too_many_batches.
The result appends gender, probability, sample_size, country, source,
matched_as, first_name, middle_name, last_name and name_type to every
row. A CSV result starts with a UTF-8 byte order mark so that Excel reads it
correctly; strip the first three bytes before handing it to fgetcsv.
Webhooks
Add an endpoint under Webhooks in the dashboard, and NameGender sends a signed
POST to it when a file job completes or fails, and when credits are about to
run out (credits.low) or have run out (credits.depleted, checked hourly).
Webhooks::verify checks the signature and the timestamp, and returns the
event.
use NameGender\Webhooks; use NameGender\WebhookVerificationException; try { $event = Webhooks::verify( file_get_contents('php://input'), // the raw body, not a decoded $_POST $_SERVER['HTTP_NAMEGENDER_SIGNATURE'] ?? null, $_ENV['NAMEGENDER_WEBHOOK_SECRET'], ); } catch (WebhookVerificationException) { http_response_code(400); exit; } http_response_code(204); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); // PHP-FPM: send the answer now, then do the work } if ($event['type'] === 'batch.completed') { $job = $event['data']['object']; // the job, as batches()->get() returns it }
In Laravel or Symfony, pass $request->getContent() and
$request->header('NameGender-Signature') (Symfony:
$request->headers->get(...)).
Use $event['id'] (also the NameGender-Event-Id header) to ignore a delivery
you have already handled. A retry carries the same id, and order is not
guaranteed. Anything other than a 2xx within 10 seconds is retried, up to 8
attempts over about 45 hours.