Name Done uses a two-tier authentication model: a long-lived API key exchanged for a short-lived JWT. This keeps your API key off the wire for every autocomplete request.
Sign up at auth.namedone.com/signup and create an API key. It starts with nd_.
POST your API key to the token endpoint. You receive a JWT valid for 5 minutes.
Pass the JWT as a token query parameter on every autocomplete request. The SDK handles this automatically.
Your API key is a long-lived secret that starts with nd_. It is 67 characters long and cryptographically random. Never expose it in client-side code or commit it to version control.
Important: Your API key is a secret. Anyone with your key can make requests on your behalf. Store it securely (e.g. in an environment variable) and never embed it in client-side JavaScript that users can inspect.
https://token.namedone.com/v1{ "apiKey": "nd_..."}{ "token": "eyJhbGciOiJIUzI1NiIs...", "expiresIn": 300, "tokenType": "Bearer"}| Status | Error | Description |
|---|---|---|
| 400 | Invalid JSON body | Request body is not valid JSON. |
| 401 | Invalid API key | API key not found or prefix mismatch. |
| 401 | API key has been revoked | The key was revoked in the portal. |
| 402 | Insufficient credits | Account has no remaining credits. |
| 403 | Account suspended | Account has been suspended. |
| 405 | Method not allowed | Only POST is supported. |
The JWT is signed with HMAC-SHA256 (HS256). It contains the following claims:
| Claim | Type | Description |
|---|---|---|
| sub | string | Account ID (e.g. acct_123) |
| jti | string | Unique token ID (for session tracking) |
| kid | string | Signing key ID (e.g. v1) |
| tv | number | Token version (for account-level revocation) |
| iat | number | Issued-at timestamp (Unix seconds) |
| exp | number | Expiry timestamp (Unix seconds, 5 min after iat) |
The @namedone/autocomplete SDK handles token exchange, caching, and refresh automatically. Just pass your API key and the SDK does the rest.
1import { createClient } from "@namedone/autocomplete"23// The SDK creates a CachedTokenClient internally4const nd = createClient("nd_...")56// First call — fetches a JWT, then queries autocomplete7const { results } = await nd.firstNames("jo")89// Subsequent calls within 5 min — reuses cached JWT10const { results } = await nd.lastNames("sm")1112// After 5 min — automatically refreshes the JWT13const { results } = await nd.postcodes("SW1A")The SDK prefetches the JWT on mount when you call prefetchToken(), so the first keystroke doesn't wait for a token round-trip.
For advanced use cases, you can manage tokens yourself using the @namedone/token package.
1import { TokenClient } from "@namedone/token"2import { AutocompleteClient } from "@namedone/autocomplete"34// Exchange API key for JWT5const tokens = new TokenClient({ apiKey: "nd_..." })6const { token } = await tokens.getToken()78// Use the JWT directly9const client = new AutocompleteClient({ token })10const { results } = await client.firstNames("jo")Or use CachedTokenClient for automatic caching and refresh:
1import { CachedTokenClient } from "@namedone/token"2import { AutocompleteClient } from "@namedone/autocomplete"34const tokens = new CachedTokenClient({ apiKey: "nd_..." })56// AutocompleteClient calls tokens.getToken() on each request7const client = new AutocompleteClient({8 tokenProvider: () => tokens.getToken().then(t => t.token),9})1011const { results } = await client.firstNames("jo")If you're not using the SDK, you can exchange your API key and query the API directly:
1# 1. Exchange your API key for a JWT2curl -X POST https://token.namedone.com/v1 \3 -H "Content-Type: application/json" \4 -d '{"apiKey":"nd_..."}'56# Response:7# {"token":"eyJ...","expiresIn":300,"tokenType":"Bearer"}89# 2. Query autocomplete with the JWT10curl "https://autocomplete.namedone.com/v1/first-name/jo?token=eyJ..."The JWT is passed as a token query parameter (not an Authorization header). This avoids triggering CORS preflight (OPTIONS) requests — a GET with no custom headers is a "simple request" that browsers send without preflight. The CloudFront Function strips the token from the query string before it reaches the origin.
JWTs are valid for 5 minutes. The SDK's CachedTokenClient refreshes the token 30 seconds before expiry. Concurrent requests share a single in-flight refresh (deduplication), so you can safely call getToken() on every request.
// First call — hits the APIconst t1 = await tokens.getToken()// Second call — returns cached token (no network)const t2 = await tokens.getToken()// After 4.5 min — refreshes 30s before expiryconst t3 = await tokens.getToken()tv) claim invalidates all previously issued tokens when incremented.