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

# Create Contact

> Add a new contact (lead) to your CRM, with optional attributes. Fails with 409 if the number is already a contact.

> [!NOTE]
>
> Adds a lead to your [CRM](https://docs.callkaro.ai/crm/introduction.md) from your own system, such as a website form, an ad platform or your backend. The contact appears in the CRM straight away, with any attributes you send.

## Quick Example

```bash theme={null}
curl -X POST "https://api.callkaro.ai/contact/create" \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: YOUR_API_KEY" \
  -d '{
    "to_number": "+919876543210",
    "attributes": [
      { "key": "first_name", "value": "Rahul" },
      { "key": "city", "value": "Pune" }
    ]
  }'
```

## Use Cases

* **Website forms**: save a lead the moment someone submits a form
* **Ad and lead platforms**: push leads from your lead source into the CRM as they arrive
* **Your own backend**: create a contact when a customer signs up or places an order

To also start a workflow for the lead, use [Assign to Workflow](https://docs.callkaro.ai/api-reference/workflow-assign.md) instead. It creates the contact if needed and saves the same attributes.

## Where to find the values

| Field | Where it comes from |
| - | - |
| `X-API-KEY` | **API Key** in the dashboard sidebar. The contact is created on the account this key belongs to. |
| `to_number` | The lead's phone number with country code. |
| `attributes[].key` | The name of an attribute in **CRM → Attributes**. See [Attributes](https://docs.callkaro.ai/crm/attributes.md). |

## Phone numbers

`to_number` is saved as digits with the country code, the same way the CRM stores every contact:

* Spaces, dashes, brackets and `+` are removed: `+91 98765-43210` is saved as `919876543210`.
* A 10-digit number is treated as Indian, and `91` is added: `9876543210` is saved as `919876543210`.

So `+919876543210`, `919876543210` and `9876543210` are all the same contact.

## How attributes are saved

Each row in `attributes` is a `key` and a `value`.

* **Matching names**: `key` is matched to your CRM attributes ignoring case, spaces, underscores and hyphens, so `"First Name"` matches `first_name`.
* **Types**: the value is checked against the attribute's type. A number attribute needs a number, a date needs a date, a yes/no attribute needs `true` or `false`, and an enum value must be one of its options.
* **Limits**: up to 50 rows per request, and each value at most 1000 characters. A value must be a string, number or boolean, not an object or a list.

> [!WARNING]
>
> Only attributes that already exist in **CRM → Attributes** are saved. A key with no matching attribute is not created; it is listed under `ignored` in the response. Create the attribute first.

The response reports what happened to every row, so a typo does not go unnoticed:

```json theme={null}
"attributes": {
  "updated": ["first_name"],
  "kept_existing": [],
  "ignored": ["frist_name"],
  "invalid": [{ "key": "age", "reason": "not a valid number" }]
}
```

## Errors worth handling

> **409 Contact already exists**
>
> The number is already a contact on this account. Use [Update Contact](https://docs.callkaro.ai/api-reference/contact-update.md) to change its attributes.

> **401 Invalid API key**
>
> The `X-API-KEY` header is missing or does not belong to any account. Copy the key again from **API Key** in the dashboard.

> **403 Account is inactive**
>
> The account the key belongs to has been deactivated. Contact support.

> **400 Missing to\_number, or a problem with attributes**
>
> The body has no phone number, `attributes` is not a list, or a row has no `key`, an object or list as its `value`, or a value longer than 1000 characters. The message says which.

> [!WARNING]
>
> Do not retry a `400`, `401`, `403` or `409`: the same request will get the same answer. Only `5xx` responses are worth retrying.


## OpenAPI

````yaml POST /contact/create
openapi: 3.1.0
info:
  title: CallKaro AI API
  description: Campaign and outbound call management API for CallKaro AI voice agents
  version: 1.0.0
  contact:
    name: CallKaro AI Support
    email: support@callkaro.ai
    url: https://callkaro.ai
servers:
  - url: https://api.callkaro.ai
    description: Production server
security:
  - ApiKeyAuth: []
paths:
  /contact/create:
    post:
      tags:
        - Endpoints
      summary: Create Contact
      description: >-
        Add a new contact (lead) to your CRM, with optional attributes. Fails
        with 409 if the number is already a contact.
      operationId: createContact
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactWriteRequest'
            example:
              to_number: '+919876543210'
              attributes:
                - key: first_name
                  value: Rahul
                - key: city
                  value: Pune
      responses:
        '201':
          description: Contact created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactWriteResponse'
              example:
                status: done
                message: Contact created
                contact:
                  to_number: '919876543210'
                  channels: []
                  attributes:
                    first_name: Rahul
                    city: Pune
                  created_at: '2026-10-27 11:42:05.118'
                  updated_at: '2026-10-27 11:42:05.118'
                  last_message_at: null
                attributes:
                  updated:
                    - first_name
                    - city
                  kept_existing: []
                  ignored: []
                  invalid: []
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: error
                message: attributes must be a list of { key, value, replace }
        '401':
          description: Missing or unknown X-API-KEY
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: error
                message: Invalid API key
        '403':
          description: The account this key belongs to is inactive
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: error
                message: Account is inactive
        '409':
          description: The number is already a contact on this account
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: error
                message: Contact already exists. Use /contact/update to change it.
components:
  schemas:
    ContactWriteRequest:
      type: object
      required:
        - to_number
      properties:
        to_number:
          type: string
          description: >-
            Phone number with country code. A 10-digit number is read as Indian
            (+91). Spaces, dashes and + are ignored.
          example: '+919876543210'
        attributes:
          type: array
          maxItems: 50
          items:
            $ref: '#/components/schemas/ContactAttribute'
          description: >-
            CRM attributes to save on the contact. Only attributes that already
            exist in CRM > Attributes are saved.
    ContactWriteResponse:
      type: object
      properties:
        status:
          type: string
          example: done
        message:
          type: string
          example: Contact created
        contact:
          $ref: '#/components/schemas/Contact'
        attributes:
          $ref: '#/components/schemas/ContactAttributeReport'
    ErrorResponse:
      type: object
      properties:
        status:
          type: string
          example: error
        message:
          type: string
          description: Error description
          example: 'Missing required field: to_number'
    ContactAttribute:
      type: object
      required:
        - key
        - value
      properties:
        key:
          type: string
          description: >-
            Name of an attribute in CRM > Attributes. Matched ignoring case,
            spaces, underscores and hyphens.
          example: first_name
        value:
          description: >-
            A string, number or boolean, at most 1000 characters. Checked
            against the attribute's type.
          oneOf:
            - type: string
            - type: number
            - type: boolean
          example: Rahul
        replace:
          type: boolean
          description: >-
            Overwrite a value the contact already has. Defaults to false on
            create and true on update.
    Contact:
      type: object
      properties:
        to_number:
          type: string
          description: 'Phone number as stored: digits only, with country code'
          example: '919876543210'
        channels:
          type: array
          items:
            type: string
          description: Channels this contact has been reached on
          example:
            - whatsapp
        attributes:
          type: object
          additionalProperties: true
          description: Attribute name to value
          example:
            first_name: Rahul
            city: Pune
        created_at:
          type: string
          description: IST, YYYY-MM-DD HH:mm:ss.SSS
          example: '2026-10-27 11:42:05.118'
        updated_at:
          type: string
          description: IST, YYYY-MM-DD HH:mm:ss.SSS
          example: '2026-10-27 11:42:05.118'
        last_message_at:
          type: string
          nullable: true
          description: IST time of the last WhatsApp message, or null
          example: null
    ContactAttributeReport:
      type: object
      description: What happened to every row of `attributes`
      properties:
        updated:
          type: array
          items:
            type: string
          description: Attributes saved
        kept_existing:
          type: array
          items:
            type: string
          description: >-
            Attributes left as they were: replace was false and a value existed,
            or the value was set by hand in the CRM
        ignored:
          type: array
          items:
            type: string
          description: Keys with no matching attribute in CRM > Attributes
        invalid:
          type: array
          items:
            type: object
            properties:
              key:
                type: string
              reason:
                type: string
          description: Values that did not fit the attribute's type or options
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
      description: API key from https://callkaro.ai/dashboard/api-key

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.