# Person Search API
> Find people by name, company, job title, location, or any criteria you describe
**Base URL:** `https://api.nyne.ai`
**Endpoint:** `https://api.nyne.ai/person/search`

---

## Overview
The Person Search API helps you find people who match specific criteria. Describe who you're looking for in plain English, like "marketing directors at tech startups in Austin" or "CFOs at healthcare companies with 100+ employees", and get back a list of matching people with their contact information.
### What You Get
- **Contact Information:** Verified email addresses and phone numbers for each match- **Professional Details:** Current job title, company, and work history- **Social Profiles:** LinkedIn, Twitter, and other social media links- **AI-Powered Matching:** Results are ranked by how well they match your search criteria
## Authentication

All requests require header authentication:

```
X-API-Key: YOUR_API_KEY
X-API-Secret: YOUR_API_SECRET
```

## Rate Limits

| Limit | Value |
|-------|-------|
| Per Minute | 60 requests |
| Per Hour | 1000 requests |
| Monthly | Varies by plan |

### Response Headers

Responses from endpoints that perform rate-limit checks include both legacy and standard rate-limit headers:

| Header | Description |
|--------|-------------|
| `X-RateLimit-Limit` | Active per-minute or per-hour limit |
| `X-RateLimit-Remaining` | Remaining requests in the active window |
| `X-RateLimit-Reset` | Unix timestamp when the active window resets |
| `RateLimit-Limit` | Active per-minute or per-hour limit |
| `RateLimit-Remaining` | Remaining requests in the active window |
| `RateLimit-Reset` | Seconds until the active window resets |
| `Retry-After` | Seconds to wait before retrying; present on HTTP `429` rate-limit responses |

Monthly quota responses include quota-specific headers when available:

| Header | Description |
|--------|-------------|
| `X-Quota-Limit` | Monthly request or credit limit |
| `X-Quota-Used` | Amount used in the current billing cycle |
| `X-Quota-Remaining` | Amount remaining in the current billing cycle |
| `X-Quota-Reset` | Unix timestamp when the current billing cycle resets |

## Credit Usage

- **Fast Search:**  credits per search (<code>type: "light"</code>) — basic search, fastest response (3&ndash;40 seconds)
- **Pro Search:**  credits per search (<code>type: "premium"</code>) — comprehensive search, best quality (30&ndash;300 seconds)
- **Smart Ranking:**  additional credits when <code>profile_scoring: true</code> — AI-powered relevance scoring of results
- **Candidate Insights:**  additional credits when <code>insights: true</code> — AI-generated insights about each result
- **Realtime Profiles:**  additional credits when <code>high_freshness: true</code> — prioritize recently updated profiles
- **Filter Without Contact Data:**  credits search without email/phone enrichment (base cost per result)
- **Enrich Phones:**  additional credits when <code>show_phone_numbers: true</code> — include phone numbers in results
- **Enrich Emails:**  additional credits when <code>show_emails: true</code> — include email addresses in results
- **Require Emails:**  additional credits when <code>require_emails: true</code> — only return profiles with email addresses
- **Require Phones:**  additional credits when <code>require_phone_numbers: true</code> — only return profiles with phone numbers
- **Require Contact Info:**  additional credits when <code>require_phones_or_emails: true</code> — only return profiles with phone OR email
> Credits are consumed based on the actual features used in your search request. You must have a positive credit balance to make search requests. Using <code>cursor</code> or <code>request_id</code> for cached results is free.
---

## POST /person/searchSearch for professional contacts using natural language queries.
### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `query` | string | Yes | Natural language search query describing who you're looking for (max 1000 chars). Required unless cursor or request_id is provided for pagination. |
| `limit` | integer | No | Maximum number of results to return per request (default: `10`) |
| `offset` | integer | No | Starting position in the result set, 0-indexed. Use with limit for pagination. Combined offset + limit cannot exceed 1000. |
| `cursor` | string | No | Opaque pagination token from a previous response's next_cursor field. Recommended for pagination. The cursor includes position and page size. When provided, query and limit are optional (you can override limit if needed). |
| `request_id` | string | No | Request ID from a previous response to continue fetching results from the same search. When provided, query is optional. If both are provided, query must match the original. |
| `force_new` | boolean | No | Force a fresh search even if cached results exist for the same query (default: `false`) |
| `type` | string | No | Search quality tier. Trade-off between speed and result quality. (default: `premium`) |
| `show_emails` | boolean | No | Include email addresses in results (default: `false`) |
| `show_phone_numbers` | boolean | No | Include phone numbers in results (default: `false`) |
| `require_emails` | boolean | No | Only return profiles that have email addresses available (default: `false`) |
| `require_phone_numbers` | boolean | No | Only return profiles that have phone numbers available (default: `false`) |
| `require_phones_or_emails` | boolean | No | Only return profiles that have either phone numbers OR email addresses (default: `false`) |
| `insights` | boolean | No | Include AI-generated insights about each result's relevance to your query. Not available for light type searches &mdash; will be ignored. (default: `false`) |
| `high_freshness` | boolean | No | Prioritize recently updated profiles in results. Not available for light type searches &mdash; will be ignored. (default: `false`) |
| `profile_scoring` | boolean | No | Include AI-powered relevance scoring for each result. When enabled, each result includes a score field indicating how well the profile matches your query. (default: `false`) |
| `callback_url` | string | No | URL to receive results asynchronously via webhook |
| `custom_filters` | object | No | Structured filters for precise search targeting. See Custom Filters section for all available fields. |
| `exclude` | array | No | Array of LinkedIn usernames to exclude from search results. Use this to filter out people you've already contacted or don't want in results. Accepts a single string or an array of strings (a single string will be automatically converted to an array). |

> **Required:** The <code>query</code> parameter is required unless <code>cursor</code> or <code>request_id</code> is provided for pagination.
### Request Examples

**With Advanced Features:**

```json
{
  "query": "Software engineers at Fortune 500 companies in San Francisco with machine learning experience",
  "type": "premium",
  "limit": 25,
  "show_emails": true,
  "show_phone_numbers": true,
  "insights": true,
  "high_freshness": false,
  "profile_scoring": true
}
```

**Basic Request:**

```json
{
  "query": "Software engineers at Fortune 500 companies in San Francisco",
  "type": "light",
  "limit": 25,
  "show_emails": true,
  "show_phone_numbers": true
}
```

### Code Examples

**cURL:**

```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 '{
    "query": "Sales managers at Fortune 500 companies in San Francisco",
    "limit": 25
  }'
```

**Python:**

```python
import requests
import json

url = "https://api.nyne.ai/person/search"
headers = {
    "X-API-Key": "YOUR_API_KEY",
    "X-API-Secret": "YOUR_API_SECRET",
    "Content-Type": "application/json"
}

data = {
    "query": "Sales managers at Fortune 500 companies in San Francisco",
    "limit": 25
}

response = requests.post(url, headers=headers, json=data)
result = response.json()
print(json.dumps(result, indent=2))
```

**JavaScript:**

```javascript
const url = "https://api.nyne.ai/person/search";
const headers = {
    "X-API-Key": "YOUR_API_KEY",
    "X-API-Secret": "YOUR_API_SECRET",
    "Content-Type": "application/json"
};

const data = {
    query: "Sales managers at Fortune 500 companies in San Francisco",
    limit: 25
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.error("Error:", error));
```

**PHP:**

```php
<?php
$url = "https://api.nyne.ai/person/search";
$headers = [
    "X-API-Key: YOUR_API_KEY",
    "X-API-Secret: YOUR_API_SECRET",
    "Content-Type: application/json"
];

$data = [
    "query" => "Sales managers at Fortune 500 companies in San Francisco",
    "limit" => 25
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$result = json_decode($response, true);
curl_close($ch);

echo json_encode($result, JSON_PRETTY_PRINT);
?>
```

### Response Codes

| Code | Description |
|------|-------------|
| 200 | Search completed successfully |
| 400 | Invalid request parameters or missing query |
| 401 | Invalid API credentials |
| 402 | Insufficient credits |
| 429 | Rate limit exceeded |

### Response Example

```json
{
  "success": true,
  "data": {
    "request_id": "abc12345_1737123456_1234",
    "status": "completed",
    "results": [
      {
        "displayname": "John Smith",
        "headline": "Senior Sales Manager",
        "bio": "Experienced sales leader with 15+ years in enterprise software sales.",
        "location": "San Francisco, CA",
        "gender": "male",
        "best_business_email": "john.smith@techcorp.com",
        "best_personal_email": "johnsmith@gmail.com",
        "altemails": [
          "john.smith@techcorp.com",
          "j.smith@example.com"
        ],
        "fullphone": [
          {
            "fullphone": "+1-555-123-4567",
            "phone_type": "mobile"
          }
        ],
        "social_profiles": {
          "linkedin": {
            "url": "https://www.linkedin.com/in/johnsmith",
            "username": "johnsmith",
            "connections": 500,
            "followers": 1200,
            "photo_url": "https://media.licdn.com/..."
          }
        },
        "organizations": [
          {
            "name": "Tech Corp",
            "title": "Senior Sales Manager",
            "startDate": "2020-01",
            "location": "San Francisco, CA",
            "company_website": "https://techcorp.com",
            "industries": ["Software", "Technology"],
            "num_employees": 5000
          }
        ],
        "schools_attended": ["Stanford University", "UC Berkeley"],
        "schools_info": [
          {
            "name": "Stanford University",
            "degree": "MBA",
            "major": "Business Administration",
            "endDate": "2010"
          }
        ],
        "total_experience_years": 15,
        "is_decision_maker": true,
        "score": 0.95,
        "insights": {
          "overall_summary": "Highly relevant match - experienced sales leader at Fortune 500 company in target location",
          "query_insights": "Strong match for sales manager role with extensive enterprise experience"
        }
      }
    ],
    "offset": 0,
    "limit": 25,
    "total_stored": 25,
    "total_estimate": 500,
    "has_more": true,
    "next_cursor": "eyJvIjoyNSwiciI6ImFiYzEyMzQ1XzE3MzcxMjM0NTZfMTIzNCJ9",
    "from_cache": false,
    "credits_charged": 125
  },
  "timestamp": "2024-01-15T10:30:00Z"
}
```

---

## GET /person/search
Check the status of a request.

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `request_id` | string | Yes | The request ID returned from the search call |

### Request Example

```
GET /person/search?request_id=12345
```

### Response Codes

| Code | Description |
|------|-------------|
| 200 | Status retrieved successfully |
| 400 | Invalid request parameters |
| 401 | Invalid API credentials |
| 404 | Request ID not found |

### Response Example

```json
{
  "success": true,
  "data": {
    "request_id": "abc12345_1737123456_1234",
    "status": "completed",
    "results": [
      {
        "displayname": "John Smith",
        "headline": "Software Engineer at Tech Corp",
        "bio": "Software Engineer with expertise in web development and cloud technologies.",
        "location": "San Francisco, CA",
        "best_business_email": "john.smith@techcorp.com",
        "altemails": ["john.smith@techcorp.com", "j.smith@example.com"],
        "fullphone": [{"fullphone": "(555) 123-4567", "phone_type": "mobile"}],
        "social_profiles": {
          "linkedin": {"url": "https://linkedin.com/in/johnsmith", "username": "johnsmith"}
        },
        "organizations": [{"name": "Tech Corp", "title": "Software Engineer", "startDate": "2020-01"}]
      }
    ],
    "offset": 0,
    "limit": 10,
    "total_stored": 1,
    "total_estimate": 1,
    "has_more": false,
    "from_cache": true,
    "credits_charged": 0
  },
  "timestamp": "2024-01-15T10:30:00Z"
}
```

---

## Response Format

All API responses follow a consistent JSON format. All fields in enrichment results are **optional** and only included when data is available:
- If a field has no data, it will be omitted from the response (not included as null or empty string)- Arrays are only included if they contain at least one item- Objects are only included if they contain at least one field- The score field is only included when profile_scoring is enabled- The insights object is only included when insights is enabled- Email and phone fields are only included when show_emails or show_phone_numbers are enabled respectively
---

## Error Codes

| HTTP Code | Error Code | Description |
|-----------|------------|-------------|
| 400 | `missing_parameters` | Required parameters are missing |
| 400 | `invalid_parameters` | Invalid parameter values |
| 400 | `invalid_custom_filters` | Invalid custom_filters value. Possible causes: custom_filters is not an object, numeric range filters contain non-integer values, min value exceeds max value, or gender is not 'male' or 'female' |
| 401 | `invalid_credentials` | API key or secret is incorrect |
| 404 | `request_not_found` | Request ID not found (for status checks) |
| 429 | `rate_limit_exceeded` | Rate limit exceeded |
| 402 | `insufficient_credits` | Insufficient credit balance to complete the request |
| 500 | `internal_error` | Internal server error |

---

## Callbacks

When you provide a `callback_url`, the API sends results to your endpoint via HTTP POST.

### Retry Policy- Maximum 5 retry attempts- Exponential backoff: 1s, 5s, 15s, 1m, 5m- 30-second timeout per request- Your endpoint should return HTTP 2xx for success
Your callback endpoint should respond with HTTP 200-299. Any other code triggers a retry.

### Callback Payload Example

```json
{
  "request_id": "abc12345_1737123456_1234",
  "status": "completed",
  "success": true,
  "completed": true,
  "data": {
    "results": [...],
    "offset": 0,
    "limit": 25,
    "total_stored": 15,
    "total_estimate": 100,
    "has_more": true,
    "next_cursor": "eyJvIjoxNSwiciI6ImFiYzEyMzQ1XzE3MzcxMjM0NTZfMTIzNCJ9"
  },
  "completed_on": "2024-01-15T10:30:00Z",
  "timestamp": "2024-01-15T10:30:00Z"
}
```

---

## Best Practices

Prioritize inputs in this order for best match rates:
1. **Premium Search** (Best) — Use <code>type: "premium"</code> for the most comprehensive and highest quality results. Combine with <code>profile_scoring: true</code> for AI-ranked relevance.2. **Custom Filters** (Good) — Combine natural language queries with <code>custom_filters</code> for precise targeting. Filters provide exact matching while queries handle semantic search.3. **Cursor Pagination** (Best) — Always use <code>next_cursor</code> for pagination. It's simpler, more reliable, and cached pages are free.
**Recommendation:** For best results, use premium search type with specific natural language queries. Add custom_filters for structured criteria like location, experience years, or industry. Use cursor-based pagination to efficiently retrieve all results.
---

## Related APIs
- **Person Enrichment API** — Look up full profiles for contacts you find → `https://api.nyne.ai/documentation/person/enrichment`
- **Person Leads API** — AI-powered lead generation from natural language → `https://api.nyne.ai/documentation/person/leads`
- **Person Discover API** — Keyword-based people discovery → `https://api.nyne.ai/documentation/person/discover`