# Constructing effective requests

> Every Nyne.ai request falls into one of two shapes. Enrichment and lookup identify one person from the identifiers you already hold; search takes a filter and returns the people who match. Getting the inputs right - the right identifiers, a clean company name, only the fields you need - is what drives your hit rate, latency, and credit cost.

HTML version: https://api.nyne.ai/documentation/effective-requests

The two request shapes: **enrichment / lookup** (`POST /person/enrichment`, `POST /person/lookup-fields`) identify one person, while **search** (`POST /person/search`) describes a filter and returns everyone who matches.

## Identifiers for enrichment and lookup

Enrichment and lookup identify a single person. Send at least one of `email`, `phone`, `social_media_url`, or `name`. The more specific the identifier, the better the match: `email` and `social_media_url` resolve to exactly one person, while `name` works best when you also pass `company` and a location to disambiguate.

| key | What it is |
| --- | --- |
| email | A work or personal email address. The strongest single identifier. |
| phone | A phone number in any common format. |
| social_media_url | A profile URL, e.g. a LinkedIn page. |
| name | Full name. Works best paired with company + location to disambiguate. |
| company | Employer name. Strip legal suffixes first (see below). |
| city | City the person is in, to narrow a name match. |
| state | State or region, alongside city. |
| company_domain | Employer domain (lookup-fields), e.g. acme.com. |
| location | A free-form location string (lookup-fields). |
| postal_code | Postal or ZIP code (lookup-fields). |
| profile_url / url | A profile URL alias accepted by lookup-fields. |

Extra identifiers never hurt: each one narrows the candidate set and raises your chance of a clean, single-person match.

## Ask for only what you need: the fields array

Lookup requests take a `fields` array. Request only the fields you actually use - a narrower request is cheaper and faster, because each field can pull from a different source. Common contact fields are `best_work_email`, `best_personal_email`, and `mobile`. If you already hold specific profile URLs you want resolved, pass them in `profile_urls`.

```bash
curl -X POST https://api.nyne.ai/person/lookup-fields \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "X-API-Secret: YOUR_API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane.doe@acme.com",
    "fields": ["best_work_email", "mobile"]
  }'
```

## The email and phone shortcuts

When you need exactly one contact field, skip the `fields` array. `POST /person/email` and `POST /person/phone` are thin wrappers over lookup-fields that force the field set for you: `/person/email` forces `fields=["best_work_email"]` and `/person/phone` forces `fields=["mobile"]`, and both clear `profile_urls`. They take the same person identifiers - the simplest possible request when you only want that one value.

```bash
curl -X POST https://api.nyne.ai/person/email \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "X-API-Secret: YOUR_API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Jane Doe", "company": "acme" }'
```

```bash
curl -X POST https://api.nyne.ai/person/phone \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "X-API-Secret: YOUR_API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "social_media_url": "https://linkedin.com/in/janedoe" }'
```

Under the hood, `/person/email` is a lookup-fields call with this body forced on top of your identifiers:

```json
{
  "fields": ["best_work_email"],
  "profile_urls": []
}
```

## Start from what you know, expand outward

A hard identifier resolves to a single person on its own: an `email`, a `phone`, or a LinkedIn or other `social_media_url`. Once you have one, submit it back to enrichment to expand the record - filling out title, company, socials, and work history from that single anchor. You do not need to send anything else:

```bash
curl -X POST https://api.nyne.ai/person/enrichment \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "X-API-Secret: YOUR_API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "social_media_url": "https://linkedin.com/in/janedoe" }'
```

This "known key in, full record out" flow is the backbone of most integrations: capture whatever strong identifier a user gives you, then let enrichment fill in the rest.

## Company-name hygiene

Legal and entity suffixes throw off company matching. Before you send a `company` value, lowercase it and strip trailing suffix tokens repeatedly until none remain. So `"Acme Corp Inc"` becomes `"acme"`. Copy-paste this suffix list:

```
inc, llc, ltd, co, corp, corporation, company, gmbh, sa, ag,
plc, llp, lp, pllc, pty, group, holdings, holding, the
```

Match tokens case-insensitively and remove them one at a time from the end, so a doubled suffix like `Corp Inc` is fully cleaned. Do this to any name you send as `company` - in enrichment, lookup, the shortcuts, and the search `companies` filter alike.

## Search filters and requirements

Search does not identify one person - it takes a `custom_filters` object and returns everyone who matches. Each field in `custom_filters` is an array you can combine, plus numeric range pairs like `min_linkedin_followers` / `max_linkedin_followers`:

| custom_filters field | Matches on |
| --- | --- |
| locations | Regions, metros, or countries. |
| languages | Languages the person uses. |
| titles | Job titles or role names. |
| industries | Industry categories. |
| companies | Current or past employers. |
| universities | Schools attended. |
| keywords | Free-text terms matched across the profile. |
| degrees | Degree types held. |
| specialization_categories | Areas of specialization. |
| company_funding_stages | Funding stage of the employer. |
| company_latest_funding_stages | Most recent funding stage. |
| company_investor_names | Investors backing the employer. |

Alongside the filters, contact-requirement toggles narrow the result set to people who have the contact data you care about, and `probability_score` attaches a match probability to each result:

| parameter | Effect |
| --- | --- |
| require_emails | Keep only results that have an email. |
| require_phone_numbers | Keep only results that have a phone. |
| require_phones_or_emails | Keep only results with a phone or an email. |
| probability_score | Attach a match-probability score to each result. |

```bash
curl -X POST https://api.nyne.ai/person/search \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "X-API-Secret: YOUR_API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "custom_filters": {
      "titles": ["VP of Engineering", "CTO"],
      "locations": ["San Francisco Bay Area"],
      "industries": ["Software"],
      "min_linkedin_followers": 1000
    },
    "require_phones_or_emails": true,
    "probability_score": true,
    "limit": 10
  }'
```

Each requirement you add filters more people out and can raise the cost per result, because guaranteeing a phone or email means resolving more data. See [Credits](https://api.nyne.ai/documentation/credits.md) and [Request depth](https://api.nyne.ai/documentation/request-depth.md) for how the trade-off is priced.

## Async delivery with callback_url

Any submit can carry a `callback_url`. When the result is ready, Nyne POSTs it there instead of making you poll. The URL is validated against an allowed-hosts list, so register your host first. See [Async and webhooks](https://api.nyne.ai/documentation/async.md) for the full setup.

## What's next

- [Request depth](https://api.nyne.ai/documentation/request-depth.md) - how far Nyne digs for a result, and what that costs.
- [Credits](https://api.nyne.ai/documentation/credits.md) - what each request type charges, and when.
- [Async and webhooks](https://api.nyne.ai/documentation/async.md) - polling versus `callback_url` delivery.
- [Responses](https://api.nyne.ai/documentation/responses.md) - the envelope and the fields you get back.
