> ## Documentation Index
> Fetch the complete documentation index at: https://docs.leads-siren.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sniper Search

Search for a person across **Les Pages Rouges** (OpenSearch) and **Datagma**. Both name-based sources are queried in parallel and results are merged via Golden Record dedup (pivot on name + postal code + city).

<Warning>
  **Address and email search are restricted, each behind its own permission flag.** Only accounts with `config.allowed_services.address_search: true` may include an `address` field, and only accounts with `config.allowed_services.email_search: true` may include an `email` field. Requests that include a restricted field without the matching flag return `403 Forbidden`. Name search (`first_name` + `last_name`) remains available to everyone.
</Warning>

## Search modes

| Mode         | Fields                     | Who can use                                | Sources queried          |
| ------------ | -------------------------- | ------------------------------------------ | ------------------------ |
| **Name**     | `first_name` + `last_name` | Everyone                                   | LPR + Datagma (parallel) |
| **Address**  | `address`                  | `address_search` permission                | LPR OpenSearch only      |
| **Email**    | `email`                    | `email_search` permission                  | LPR OpenSearch only      |
| **Combined** | any mix of the above       | Each restricted field needs its permission | All applicable sources   |

At least one mode must be provided. You can send any combination — name, address, email, or all together.

## Request Body

<ParamField body="data" type="object">
  <Expandable title="properties">
    <ParamField body="first_name" type="string">
      Person's first name. Required together with `last_name` when doing a name search.
    </ParamField>

    <ParamField body="last_name" type="string">
      Person's last name. Required together with `first_name` when doing a name search.
    </ParamField>

    <ParamField body="address" type="string">
      Street address. Queries LPR OpenSearch by `address_search` field (prefix/fuzzy match).

      **Requires `address_search` permission** — see [Permissions](#permissions).
    </ParamField>

    <ParamField body="email" type="string">
      Email address. Queries LPR OpenSearch by exact `email` match.

      **Requires `email_search` permission** — see [Permissions](#permissions).
    </ParamField>

    <ParamField body="page" type="integer" default="1">
      Page number (1-based). Credits are charged only on page 1.
    </ParamField>

    <ParamField body="per_page" type="integer" default="25">
      Results per page.
    </ParamField>

    <ParamField body="user_id" type="string">
      Required when authenticating via JWT Bearer token instead of `x-api-key`.
    </ParamField>
  </Expandable>
</ParamField>

## Permissions

Address and email search are each gated by their own flag on the user document. They are independent — a user can have one, both, or neither.

```json theme={null}
{
  "config": {
    "allowed_services": {
      "address_search": true,
      "email_search": true
    }
  }
}
```

| Flag             | Controls        | If `true`                  | If `false` / missing                             |
| ---------------- | --------------- | -------------------------- | ------------------------------------------------ |
| `address_search` | `address` field | User may search by address | Request with non-empty `address` returns **403** |
| `email_search`   | `email` field   | User may search by email   | Request with non-empty `email` returns **403**   |

Name search (`first_name` + `last_name`) requires no permission and is always available.

## Credit Cost

Flat rate per search (charged **only on page 1**):

| Condition                       | Cost                  |
| ------------------------------- | --------------------- |
| Any result has a phone          | **100 credits**       |
| Any result has an email         | **10 credits**        |
| Both phone and email in results | **110 credits** (max) |
| No contacts in any result       | **0 credits**         |

Subsequent pages (2, 3, …) are **free** for the same search.

## Request examples

<RequestExample>
  ```bash cURL — name search (all users) theme={null}
  curl -X POST https://search.leads-siren.com/enrichment-service/sniper-search \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "data": {
        "first_name": "Richard",
        "last_name": "Cohen"
      }
    }'
  ```

  ```bash cURL — address search (permission required) theme={null}
  curl -X POST https://search.leads-siren.com/enrichment-service/sniper-search \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "data": {
        "address": "2 avenue saint maurice du valais"
      }
    }'
  ```

  ```bash cURL — email search (permission required) theme={null}
  curl -X POST https://search.leads-siren.com/enrichment-service/sniper-search \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "data": {
        "email": "cohenrichard@hotmail.com"
      }
    }'
  ```

  ```bash cURL — name + address + email combined (each restricted field needs its permission) theme={null}
  curl -X POST https://search.leads-siren.com/enrichment-service/sniper-search \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "data": {
        "first_name": "Richard",
        "last_name": "Cohen",
        "address": "2 avenue saint maurice",
        "email": "cohenrichard@hotmail.com",
        "page": 1,
        "per_page": 25
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      "https://search.leads-siren.com/enrichment-service/sniper-search",
      headers={"x-api-key": "YOUR_API_KEY"},
      json={
          "data": {
              "first_name": "Michel",
              "last_name": "Jean",
              "page": 1,
              "per_page": 25,
          }
      },
  )
  print(resp.json())
  ```
</RequestExample>

## Response

<ResponseExample>
  ```json 200 theme={null}
  {
    "total": 2,
    "page": 1,
    "per_page": 25,
    "total_pages": 1,
    "results": [
      {
        "nom_complet": "Richard Cohen",
        "prenom": "Richard",
        "nom": "Cohen",
        "email": "cohenrichard@hotmail.com",
        "adresse": "2 avenue saint maurice du valais",
        "code_postal": "94410",
        "ville": "ST MAURICE",
        "departement": "94",
        "telephone_mobile": "+33612211558",
        "telephone_autres": null,
        "date_naissance": "28/04/1948",
        "source": "LPR"
      }
    ]
  }
  ```

  ```json 403 theme={null}
  {
    "detail": "Address search is not enabled for your account"
  }
  ```

  ```json 403 theme={null}
  {
    "detail": "Email search is not enabled for your account"
  }
  ```

  ```json 400 theme={null}
  {
    "detail": "Provide first_name+last_name, address, and/or email"
  }
  ```
</ResponseExample>

## Response fields

| Field                        | Type           | Description                                        |
| ---------------------------- | -------------- | -------------------------------------------------- |
| `total`                      | integer        | Total unique results across all pages              |
| `page`                       | integer        | Current page                                       |
| `per_page`                   | integer        | Page size                                          |
| `total_pages`                | integer        | Total number of pages                              |
| `results`                    | array          | Matching person records                            |
| `results[].nom_complet`      | string         | Full display name                                  |
| `results[].prenom`           | string         | First name                                         |
| `results[].nom`              | string         | Last name                                          |
| `results[].email`            | string \| null | Email address                                      |
| `results[].telephone_mobile` | string \| null | Primary mobile phone                               |
| `results[].telephone_autres` | string \| null | Other phones (`;` separated)                       |
| `results[].adresse`          | string         | Street address                                     |
| `results[].code_postal`      | string         | Postal code                                        |
| `results[].ville`            | string         | City                                               |
| `results[].departement`      | string         | Department (from postal code)                      |
| `results[].date_naissance`   | string         | Date of birth (`DD/MM/YYYY`)                       |
| `results[].source`           | string         | `"LPR"`, `"Datagma"`, or `"Datagma+LPR"` if merged |
