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

# Overview

> Endpoint specification for receiving contacts from Enginy

<Warning>
  **Important**: This section describes the API endpoint that **your system must implement** to receive
  contacts from Enginy. This is not a Enginy API endpoint — it is the interface specification that Enginy will
  call on your CRM.
</Warning>

## Overview

When exporting leads from Enginy, Enginy will call your `/contacts` endpoint to create contacts in batch. Your endpoint must accept the contacts and return the CRM IDs for each created contact.

<Info>
  Enginy sends all available fields as-is. Your CRM is responsible for mapping fields to your data model.
</Info>

***

## Create Contacts

<Card title="Your Implementation Required" icon="triangle-exclamation" color="#f59e0b">
  This endpoint must be implemented on **your server**
</Card>

Enginy calls this endpoint to create contacts in your CRM.

### Request

```http theme={null}
POST /contacts
Content-Type: application/json
X-API-Key: <your-api-key>
```

### Request Body

```json theme={null}
{
  "contacts": [
    {
      "externalId": "123",
      "email": "john.doe@example.com",
      "firstName": "John",
      "lastName": "Doe",
      "phone": "+1234567890",
      "company": "Acme Inc",
      "title": "CEO",
      "linkedinUrl": "https://linkedin.com/in/johndoe"
      // ... additional fields
    }
  ]
}
```

### Request Fields

| Field                    | Type   | Description                                                              |
| ------------------------ | ------ | ------------------------------------------------------------------------ |
| `contacts`               | array  | Array of contact objects to create                                       |
| `contacts[].externalId`  | string | **Required.** Enginy's internal lead ID. Use this to map responses back. |
| `contacts[].email`       | string | Professional or personal email address                                   |
| `contacts[].firstName`   | string | Contact's first name                                                     |
| `contacts[].lastName`    | string | Contact's last name                                                      |
| `contacts[].phone`       | string | Mobile or direct phone number                                            |
| `contacts[].company`     | string | Company name                                                             |
| `contacts[].title`       | string | Job title                                                                |
| `contacts[].linkedinUrl` | string | LinkedIn profile URL                                                     |
| `contacts[].ownerId`     | string | Owner/assignee ID from your `/users` endpoint (if users are supported)   |

<Note>
  Additional fields from the lead record will be included. Your CRM should gracefully handle unknown fields
  (ignore them or store them as custom fields).
</Note>

<Info>
  **Owner Assignment**: If you implement the optional `/users` endpoint, Enginy will include an `ownerId`
  field when the user selects an owner during export. This allows contacts to be assigned to specific CRM
  users.
</Info>

### Common Additional Fields

These fields may be included depending on the lead data in Enginy:

| Field                     | Type   | Description                            |
| ------------------------- | ------ | -------------------------------------- |
| `location`                | string | Contact's location                     |
| `leadCountry`             | string | Contact's country                      |
| `industry`                | string | Industry                               |
| `companySize`             | string | Company size range                     |
| `domain`                  | string | Company domain                         |
| `description`             | string | Lead description                       |
| `emailVerificationStatus` | string | Email verification status              |
| `campaigns`               | string | Associated campaign names              |
| `lastContactedBy`         | string | Last identity that contacted this lead |
| `conversationTags`        | string | Tags from conversations                |
| `enrichments`             | string | Sources used for enrichment            |

***

### Response

<Tabs>
  <Tab title="Success (201)">
    Return a `201 Created` status with the created contact IDs.

    ```json theme={null}
    {
      "results": [
        {
          "externalId": "123",
          "crmId": "crm-contact-456"
        }
      ]
    }
    ```

    | Field                  | Type   | Description                                  |
    | ---------------------- | ------ | -------------------------------------------- |
    | `results`              | array  | Array of created contact mappings            |
    | `results[].externalId` | string | The `externalId` from the request            |
    | `results[].crmId`      | string | **Required.** Your CRM's ID for this contact |
  </Tab>

  <Tab title="Partial Success (201)">
    If some contacts fail, return success for those that worked. Enginy will mark failed contacts as errors.

    ```json theme={null}
    {
      "results": [
        {
          "externalId": "123",
          "crmId": "crm-contact-456"
        }
      ],
      "errors": [
        {
          "externalId": "124",
          "error": "Duplicate email address"
        }
      ]
    }
    ```
  </Tab>

  <Tab title="Error (4xx/5xx)">
    Return an appropriate error status if the entire batch fails.

    ```json theme={null}
    {
      "error": "Invalid request",
      "message": "Missing required field: contacts"
    }
    ```
  </Tab>
</Tabs>

***

## Batch Size

Enginy sends contacts in batches of up to **100 contacts** per request. Your endpoint should be able to handle this batch size efficiently.

<Tip>
  If you need to process contacts individually due to CRM limitations, consider implementing internal queuing
  to avoid timeout issues.
</Tip>

***

## Testing Your Endpoint

Test your contacts endpoint with this curl command:

```bash theme={null}
curl -X POST https://your-crm.com/contacts \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      {
        "externalId": "test-123",
        "email": "test@example.com",
        "firstName": "Test",
        "lastName": "User",
        "company": "Test Company"
      }
    ]
  }'
```

Expected response:

```json theme={null}
{
  "results": [
    {
      "externalId": "test-123",
      "crmId": "your-crm-id-here"
    }
  ]
}
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Companies API" icon="building" href="/api-reference/custom-crm/companies">
    Implement the companies endpoint
  </Card>

  <Card title="Associations API" icon="link" href="/api-reference/custom-crm/associations">
    Link contacts to companies
  </Card>

  <Card title="Examples" icon="code" href="/api-reference/custom-crm/examples">
    See complete implementation examples
  </Card>
</CardGroup>
