> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.theary.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage Search Contacts

> Get, add, update, remove, or mark accuracy for contacts on a search contact plan

# Manage Search Contacts

Use these endpoints to inspect or change verification contacts after an order has been created. All five operations are scoped to a search within an order.

<Note>
  Contact mutations are allowed only when the search is in `IN_PROGRESS` or `COMPLETED` status.
</Note>

<Note>
  Successful mutations emit a `verification.notification` webhook with `notificationType` set to
  `CONTACT_PLAN_ADDED`, `CONTACT_PLAN_UPDATED`, `CONTACT_PLAN_REMOVED`, `CONTACT_PLAN_MARKED_ACCURATE`, or
  `CONTACT_PLAN_MARKED_INACCURATE`. Notifications include `metadata.contactId` and, when available,
  `metadata.contactName`. Accuracy notifications also include `metadata.accuracyStatus` and `metadata.reason`.
</Note>

## Shared Path Parameters

The following path parameters apply to every operation on this page.

<ParamField path="orderId" type="string" required>
  Verification order ID (UUID).
</ParamField>

<ParamField path="searchId" type="string" required>
  Search ID (UUID) within the order.
</ParamField>

## Get Contacts

Returns the persisted contacts for a search, including removed contacts when present.

<Note>
  This operation is read-only and does not emit a `CONTACT_PLAN` notification or any other webhook event.
</Note>

### Response

<ResponseField name="success" type="boolean" />

<ResponseField name="searchId" type="string" />

<ResponseField name="externalSearchId" type="string | null" />

<ResponseField name="contacts" type="array">
  Contact records in the persisted contact plan, including removed contacts when present.
</ResponseField>

<ResponseField name="parentOrgResearch" type="object">
  Parent-organization research metadata when available.
</ResponseField>

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -sS -X GET "https://sandbox.theary.ai/background-check/v1/orders/550e8400-e29b-41d4-a716-446655440000/searches/7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111/contacts" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -H "Accept: application/json"
  ```

  ```javascript JavaScript theme={null}
  const orderId = '550e8400-e29b-41d4-a716-446655440000'
  const searchId = '7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111'
  const response = await fetch(
    `https://sandbox.theary.ai/background-check/v1/orders/${orderId}/searches/${searchId}/contacts`,
    {
      method: 'GET',
      headers: {
        Authorization: 'Bearer YOUR_JWT_TOKEN',
        Accept: 'application/json',
      },
    },
  )

  const result = await response.json()
  ```

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

  order_id = "550e8400-e29b-41d4-a716-446655440000"
  search_id = "7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111"
  response = requests.get(
      f"https://sandbox.theary.ai/background-check/v1/orders/{order_id}/searches/{search_id}/contacts",
      headers={
          "Authorization": "Bearer YOUR_JWT_TOKEN",
          "Accept": "application/json",
      },
  )

  result = response.json()
  ```
</CodeGroup>

### Example Response

```json theme={null}
{
  "success": true,
  "searchId": "7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111",
  "externalSearchId": "client-emp-001",
  "contacts": [],
  "parentOrgResearch": {}
}
```

## Add Contact

Adds a contact to the active contact plan.

### Request Body

<ParamField body="name" type="string" required>
  Contact or department name.
</ParamField>

<ParamField body="entityName" type="string" required>
  Organization associated with the contact.
</ParamField>

<ParamField body="contactMethods" type="array" required>
  One or more contact method objects. Each method may include `email`, `phone`, or `fax`, and must include `confidence` and
  `source`.
</ParamField>

<ParamField body="title" type="string">
  Contact's job title or role.
</ParamField>

<ParamField body="confidence" type="number" required>
  Overall confidence score from `0` to `1`.
</ParamField>

<ParamField body="location" type="string" required>
  Contact location.
</ParamField>

<ParamField body="executeOutboundImmediately" type="boolean">
  When `true`, queues outbound attempts for the newly added contact immediately.
</ParamField>

### Response

<ResponseField name="success" type="boolean" />

<ResponseField name="searchId" type="string" />

<ResponseField name="externalSearchId" type="string | null" />

<ResponseField name="contactId" type="string" />

<ResponseField name="outboundQueued" type="boolean" />

<ResponseField name="queuedCount" type="number" />

<ResponseField name="webhookEmitted" type="boolean">
  `true` when the contact-plan mutation notification was queued for delivery.
</ResponseField>

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -sS -X POST "https://sandbox.theary.ai/background-check/v1/orders/550e8400-e29b-41d4-a716-446655440000/searches/7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111/contact" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "HR Department",
      "entityName": "Acme Corporation",
      "contactMethods": [
        {
          "email": "hr@acme.com",
          "confidence": 0.9,
          "source": "manual_client_entry"
        }
      ],
      "title": "HR Manager",
      "confidence": 0.85,
      "location": "New York, NY",
      "executeOutboundImmediately": false
    }'
  ```

  ```javascript JavaScript theme={null}
  const orderId = '550e8400-e29b-41d4-a716-446655440000'
  const searchId = '7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111'
  const response = await fetch(
    `https://sandbox.theary.ai/background-check/v1/orders/${orderId}/searches/${searchId}/contact`,
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer YOUR_JWT_TOKEN',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        name: 'HR Department',
        entityName: 'Acme Corporation',
        contactMethods: [
          {
            email: 'hr@acme.com',
            confidence: 0.9,
            source: 'manual_client_entry',
          },
        ],
        title: 'HR Manager',
        confidence: 0.85,
        location: 'New York, NY',
        executeOutboundImmediately: false,
      }),
    },
  )

  const result = await response.json()
  ```

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

  order_id = "550e8400-e29b-41d4-a716-446655440000"
  search_id = "7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111"
  response = requests.post(
      f"https://sandbox.theary.ai/background-check/v1/orders/{order_id}/searches/{search_id}/contact",
      headers={"Authorization": "Bearer YOUR_JWT_TOKEN"},
      json={
          "name": "HR Department",
          "entityName": "Acme Corporation",
          "contactMethods": [
              {
                  "email": "hr@acme.com",
                  "confidence": 0.9,
                  "source": "manual_client_entry",
              }
          ],
          "title": "HR Manager",
          "confidence": 0.85,
          "location": "New York, NY",
          "executeOutboundImmediately": False,
      },
  )

  result = response.json()
  ```
</CodeGroup>

### Example Response

```json theme={null}
{
  "success": true,
  "searchId": "7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111",
  "externalSearchId": "client-emp-001",
  "contactId": "123e4567-e89b-12d3-a456-426614174001",
  "outboundQueued": false,
  "queuedCount": 0,
  "webhookEmitted": true
}
```

## Update Contact

Replaces the editable fields for an existing contact.

### Request Body

<ParamField body="contactId" type="string" required>
  Contact ID returned by the contact plan or add contact response.
</ParamField>

<ParamField body="name" type="string" required>
  Contact or department name.
</ParamField>

<ParamField body="entityName" type="string" required>
  Organization associated with the contact.
</ParamField>

<ParamField body="contactMethods" type="array" required>
  Replacement contact methods for this contact. Pending scheduled attempts are cancelled or retargeted when destinations change.
</ParamField>

<ParamField body="confidence" type="number" required>
  Overall confidence score from `0` to `1`.
</ParamField>

<ParamField body="location" type="string" required>
  Contact location.
</ParamField>

<ParamField body="metadata" type="object">
  Optional replacement metadata for this contact. Because this endpoint uses `PUT`, metadata from the previous contact is not
  preserved unless you include it in this object. By default the API stores `source: "manual_client_entry"` and `reason: "Manually
      update contact using endpoint"`, then stamps `lastEditedBy` and `lastEditedAt`.
</ParamField>

### Response

<ResponseField name="success" type="boolean" />

<ResponseField name="searchId" type="string" />

<ResponseField name="externalSearchId" type="string | null" />

<ResponseField name="contactId" type="string" />

<ResponseField name="cancelledScheduledAttempts" type="number" />

<ResponseField name="scheduledFollowUps" type="number" />

<ResponseField name="webhookEmitted" type="boolean" />

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -sS -X PUT "https://sandbox.theary.ai/background-check/v1/orders/550e8400-e29b-41d4-a716-446655440000/searches/7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111/contact" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "contactId": "123e4567-e89b-12d3-a456-426614174001",
      "name": "HR Department",
      "entityName": "Acme Corporation",
      "contactMethods": [
        {
          "email": "hr-updated@acme.com",
          "confidence": 0.9,
          "source": "manual_client_entry"
        }
      ],
      "confidence": 0.9,
      "location": "New York, NY",
      "metadata": {
        "source": "manual_client_entry",
        "reason": "Manually update contact using endpoint"
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const orderId = '550e8400-e29b-41d4-a716-446655440000'
  const searchId = '7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111'
  const response = await fetch(
    `https://sandbox.theary.ai/background-check/v1/orders/${orderId}/searches/${searchId}/contact`,
    {
      method: 'PUT',
      headers: {
        Authorization: 'Bearer YOUR_JWT_TOKEN',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        contactId: '123e4567-e89b-12d3-a456-426614174001',
        name: 'HR Department',
        entityName: 'Acme Corporation',
        contactMethods: [
          {
            email: 'hr-updated@acme.com',
            confidence: 0.9,
            source: 'manual_client_entry',
          },
        ],
        confidence: 0.9,
        location: 'New York, NY',
        metadata: {
          source: 'manual_client_entry',
          reason: 'Manually update contact using endpoint',
        },
      }),
    },
  )

  const result = await response.json()
  ```

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

  order_id = "550e8400-e29b-41d4-a716-446655440000"
  search_id = "7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111"
  response = requests.put(
      f"https://sandbox.theary.ai/background-check/v1/orders/{order_id}/searches/{search_id}/contact",
      headers={"Authorization": "Bearer YOUR_JWT_TOKEN"},
      json={
          "contactId": "123e4567-e89b-12d3-a456-426614174001",
          "name": "HR Department",
          "entityName": "Acme Corporation",
          "contactMethods": [
              {
                  "email": "hr-updated@acme.com",
                  "confidence": 0.9,
                  "source": "manual_client_entry",
              }
          ],
          "confidence": 0.9,
          "location": "New York, NY",
          "metadata": {
              "source": "manual_client_entry",
              "reason": "Manually update contact using endpoint",
          },
      },
  )

  result = response.json()
  ```
</CodeGroup>

### Example Response

```json theme={null}
{
  "success": true,
  "searchId": "7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111",
  "externalSearchId": "client-emp-001",
  "contactId": "123e4567-e89b-12d3-a456-426614174001",
  "cancelledScheduledAttempts": 1,
  "scheduledFollowUps": 1,
  "webhookEmitted": true
}
```

## Mark Contact Accuracy

Records audit feedback about whether a contact is accurate.

Marking a contact inaccurate can cancel pending scheduled attempts for that contact. Marking a contact accurate can optionally
queue outbound attempts. Successful requests emit `CONTACT_PLAN_MARKED_ACCURATE` or `CONTACT_PLAN_MARKED_INACCURATE`.

### Request Body

<ParamField body="contactId" type="string" required>
  Contact ID returned by the contact plan, add contact response, or get contacts response.
</ParamField>

<ParamField body="accuracyStatus" type="string" required>
  `ACCURATE` or `INACCURATE`.
</ParamField>

<ParamField body="reason" type="string" required>
  Non-empty reason for marking the contact accurate or inaccurate. Maximum length is 2000 characters.
</ParamField>

<ParamField body="cancelFutureAttempts" type="boolean">
  Defaults to `true` when `accuracyStatus` is `INACCURATE`. Cancels future scheduled attempts for the contact.
</ParamField>

<ParamField body="executeOutboundAttempts" type="boolean">
  Defaults to `false` when `accuracyStatus` is `ACCURATE`. When `true`, queues outbound attempts for the contact.
</ParamField>

### Response

<ResponseField name="success" type="boolean" />

<ResponseField name="searchId" type="string" />

<ResponseField name="externalSearchId" type="string | null" />

<ResponseField name="contactId" type="string" />

<ResponseField name="auditId" type="string" />

<ResponseField name="webhookEmitted" type="boolean" />

<ResponseField name="outboundQueued" type="boolean">
  Present when `executeOutboundAttempts` is requested for an accurate contact.
</ResponseField>

<ResponseField name="queuedCount" type="number">
  Present when `executeOutboundAttempts` is requested for an accurate contact.
</ResponseField>

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -sS -X POST "https://sandbox.theary.ai/background-check/v1/orders/550e8400-e29b-41d4-a716-446655440000/searches/7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111/contact/mark-accuracy" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "contactId": "123e4567-e89b-12d3-a456-426614174001",
      "accuracyStatus": "INACCURATE",
      "reason": "Phone number is disconnected",
      "cancelFutureAttempts": true
    }'
  ```

  ```javascript JavaScript theme={null}
  const orderId = '550e8400-e29b-41d4-a716-446655440000'
  const searchId = '7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111'
  const response = await fetch(
    `https://sandbox.theary.ai/background-check/v1/orders/${orderId}/searches/${searchId}/contact/mark-accuracy`,
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer YOUR_JWT_TOKEN',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        contactId: '123e4567-e89b-12d3-a456-426614174001',
        accuracyStatus: 'INACCURATE',
        reason: 'Phone number is disconnected',
        cancelFutureAttempts: true,
      }),
    },
  )

  const result = await response.json()
  ```

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

  order_id = "550e8400-e29b-41d4-a716-446655440000"
  search_id = "7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111"
  response = requests.post(
      f"https://sandbox.theary.ai/background-check/v1/orders/{order_id}/searches/{search_id}/contact/mark-accuracy",
      headers={"Authorization": "Bearer YOUR_JWT_TOKEN"},
      json={
          "contactId": "123e4567-e89b-12d3-a456-426614174001",
          "accuracyStatus": "INACCURATE",
          "reason": "Phone number is disconnected",
          "cancelFutureAttempts": True,
      },
  )

  result = response.json()
  ```
</CodeGroup>

### Example Response

```json theme={null}
{
  "success": true,
  "searchId": "7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111",
  "externalSearchId": "client-emp-001",
  "contactId": "123e4567-e89b-12d3-a456-426614174001",
  "auditId": "8d8b1515-b3b3-43cd-8d25-985089be18fe",
  "webhookEmitted": true
}
```

## Remove Contact

Removes a contact from the active contact plan.

### Request Body

<ParamField body="contactId" type="string" required>
  Contact ID to remove from the active contact plan.
</ParamField>

<ParamField body="reason" type="string" required>
  Reason stored in the contact audit history.
</ParamField>

<ParamField body="cancelPendingOutbound" type="boolean">
  Defaults to `true`. Cancels pending outbound work for the removed contact.
</ParamField>

### Response

<ResponseField name="success" type="boolean" />

<ResponseField name="searchId" type="string" />

<ResponseField name="externalSearchId" type="string | null" />

<ResponseField name="contactId" type="string" />

<ResponseField name="cancelledActivities" type="number" />

<ResponseField name="webhookEmitted" type="boolean" />

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -sS -X DELETE "https://sandbox.theary.ai/background-check/v1/orders/550e8400-e29b-41d4-a716-446655440000/searches/7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111/contact" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "contactId": "123e4567-e89b-12d3-a456-426614174001",
      "reason": "Contact information is outdated",
      "cancelPendingOutbound": true
    }'
  ```

  ```javascript JavaScript theme={null}
  const orderId = '550e8400-e29b-41d4-a716-446655440000'
  const searchId = '7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111'
  const response = await fetch(
    `https://sandbox.theary.ai/background-check/v1/orders/${orderId}/searches/${searchId}/contact`,
    {
      method: 'DELETE',
      headers: {
        Authorization: 'Bearer YOUR_JWT_TOKEN',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        contactId: '123e4567-e89b-12d3-a456-426614174001',
        reason: 'Contact information is outdated',
        cancelPendingOutbound: true,
      }),
    },
  )

  const result = await response.json()
  ```

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

  order_id = "550e8400-e29b-41d4-a716-446655440000"
  search_id = "7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111"
  response = requests.delete(
      f"https://sandbox.theary.ai/background-check/v1/orders/{order_id}/searches/{search_id}/contact",
      headers={"Authorization": "Bearer YOUR_JWT_TOKEN"},
      json={
          "contactId": "123e4567-e89b-12d3-a456-426614174001",
          "reason": "Contact information is outdated",
          "cancelPendingOutbound": True,
      },
  )

  result = response.json()
  ```
</CodeGroup>

### Example Response

```json theme={null}
{
  "success": true,
  "searchId": "7c7b8f66-7f6a-4b52-9e85-8b3f5b7c1111",
  "externalSearchId": "client-emp-001",
  "contactId": "123e4567-e89b-12d3-a456-426614174001",
  "cancelledActivities": 1,
  "webhookEmitted": true
}
```

## Webhook Behavior

Successful mutations emit the contact plan using the existing `verification.notification` event. For add, update, and mark accuracy operations, `contactPlan` contains the active plan after the mutation. For remove operations, `contactPlan` contains the removed contact snapshot so consumers can see which contact was deleted even when the active plan is now empty.

```json theme={null}
{
  "event": "verification.notification",
  "data": {
    "notificationType": "CONTACT_PLAN_UPDATED",
    "contactPlan": [
      {
        "name": "HR Department",
        "entityName": "Acme Corporation",
        "method": "EMAIL",
        "destination": "hr-updated@acme.com",
        "source": "manual_client_entry",
        "confidence": 0.9
      }
    ],
    "metadata": {
      "contactId": "123e4567-e89b-12d3-a456-426614174001",
      "contactName": "HR Department"
    }
  }
}
```

See [Webhook Events](/webhooks/events#contactplanentry-object) for the full contact plan payload shape.
