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

# Créer un champ personnalisé

> Creates a custom field on your team's people. The key is derived from the label. Creating the same label with the same type again returns the existing field with `already_existed` set to `true`.

<Note>
  **Scope requis :** `CRM_WRITE`
</Note>

## Champs du body

| Champ | Type | Requis | Description |
| - | - | - | - |
| `label` | string | oui | Nom affiché, de 1 à 255 caractères, avec au moins une lettre ou un chiffre |
| `type` | string | oui | `TEXT`, `NUMBER`, `DATE` ou `BOOLEAN` |

Les champs `DROPDOWN` sont synchronisés depuis vos intégrations CRM et ne peuvent pas être créés ici.

## Dérivation de la clé

La `key` est dérivée du label : minuscules, accents supprimés, séquences de caractères non alphanumériques remplacées par `_`, tronquée à 64 caractères. `Lead Source` devient `lead_source`.

Un label qui correspond à la clé d'un champ natif est rejeté avec `ATTRIBUTE_KEY_RESERVED`. Les clés réservées sont `name`, `phone_numbers`, `company`, `job_title`, `emails`, `last_activity`, `website`, `created_at` et `updated_at`.

## Créer deux fois le même champ

L'appel peut être répété sans risque. Si un champ avec la même clé et le même type existe déjà, l'endpoint renvoie `201` avec `already_existed` à `true` et le label avec lequel il a été créé. Rien n'est créé.

```json theme={null}
{
  "data": {
    "key": "lead_source",
    "label": "Lead Source",
    "type": "TEXT",
    "already_existed": true
  }
}
```

Si la clé existe avec un autre type, la requête renvoie `409 ATTRIBUTE_KEY_CONFLICT`.

## Limites

Une équipe peut avoir jusqu'à 150 champs personnalisés `TEXT`, 50 `NUMBER`, 30 `DATE` et 30 `BOOLEAN`. Lorsqu'un type est plein, créer un autre champ de ce type renvoie `409 ATTRIBUTE_SLOTS_EXHAUSTED`.

## Erreurs

| Statut | Code | Quand |
| - | - | - |
| `400` | `ATTRIBUTE_LABEL_INVALID` | `label` est vide, dépasse 255 caractères ou ne contient ni lettre ni chiffre |
| `400` | `ATTRIBUTE_KEY_RESERVED` | Le label correspond à la clé d'un champ natif |
| `400` | `INVALID_REQUEST_BODY` | `type` est absent ou n'est pas l'un de `TEXT`, `NUMBER`, `DATE`, `BOOLEAN` |
| `403` | `API_KEY_INSUFFICIENT_SCOPE` | La clé n'a pas le scope `CRM_WRITE` |
| `404` | `TEAM_NOT_FOUND` | L'espace de travail n'utilise pas le nouveau modèle de contacts |
| `409` | `ATTRIBUTE_KEY_CONFLICT` | Un champ avec cette clé existe déjà avec un autre type |
| `409` | `ATTRIBUTE_SLOTS_EXHAUSTED` | Aucun emplacement libre pour ce type |


## OpenAPI

````yaml POST /v2/api/crm/attributes
openapi: 3.0.3
info:
  title: Allo API
  description: >-
    Allo API provides programmatic access to your Allo account, allowing you to
    manage webhooks, retrieve calls and contacts, and send SMS messages.


    All requests to `/v1/api/**` endpoints automatically go through quota
    checking and scope validation.
  version: 1.0.0
  contact:
    name: Allo Support
servers:
  - url: https://api.withallo.com
    description: Production server
security: []
tags:
  - name: Summary Templates
    description: >-
      Manage call summary templates that control how AI-generated call summaries
      are structured for your team.
  - name: Webhooks
    description: >-
      Manage webhook endpoints to receive real-time notifications about events
      in your Allo account. Each endpoint subscribes to one or more event topics
      and is verified with a signing secret.
  - name: Calls
    description: >-
      Retrieve and search call records with filtering and pagination. Filter
      calls by your Allo phone number.
  - name: Contacts
    description: >-
      Search and retrieve contact information with sorting and pagination.
      Includes engagement level tracking.
  - name: SMS
    description: Send SMS messages to phone numbers using your Allo numbers.
  - name: Phone Numbers
    description: Retrieve information about your Allo phone numbers.
  - name: Analytics
    description: Pre-computed call metrics, team performance, and outbound dial funnel
  - name: CRM
    description: Manage people, companies, and deals in your CRM.
  - name: Notes
    description: >-
      Internal team notes on conversations and CRM people, with @mention
      support. Notes are never visible to the contact.
  - name: Threads
    description: >-
      Team discussion threads attached to a conversation item (call, SMS, or
      conversation note). One thread per item.
  - name: AI Receptionist
    description: >-
      Read and write the AI receptionist configuration of a phone line: business
      details, voice, prompt, capabilities, business hours, transfer rules,
      scheduling calendars and knowledge sources.
paths:
  /v2/api/crm/attributes:
    post:
      tags:
        - CRM
      summary: Create custom contact field
      description: >-
        Creates a custom field on your team's people. The key is derived from
        the label. Creating the same label with the same type again returns the
        existing field with `already_existed` set to `true`.
      operationId: createCrmAttribute
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCrmAttributeRequest'
            example:
              label: Lead Source
              type: TEXT
      responses:
        '201':
          description: The custom field that was created, or the existing one
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/CreateCrmAttributeResult'
              example:
                data:
                  key: lead_source
                  label: Lead Source
                  type: TEXT
                  already_existed: false
        '400':
          $ref: '#/components/responses/ApiValidationError'
        '401':
          $ref: '#/components/responses/ApiUnauthorized'
        '403':
          $ref: '#/components/responses/ApiForbidden'
        '404':
          $ref: '#/components/responses/ApiNotFound'
        '409':
          $ref: '#/components/responses/ApiConflict'
        '429':
          $ref: '#/components/responses/ApiRateLimited'
      security:
        - ApiKeyAuth: []
components:
  schemas:
    CreateCrmAttributeRequest:
      type: object
      description: Request body for creating a custom contact field
      required:
        - label
        - type
      properties:
        label:
          type: string
          minLength: 1
          maxLength: 255
          description: >-
            Display name of the field. The key is derived from it: lowercase,
            accents removed, runs of non-alphanumeric characters replaced by
            `_`, truncated to 64 characters. Must contain at least one letter or
            digit and must not resolve to a built-in field key such as `name`,
            `company` or `website`.
          example: Lead Source
        type:
          type: string
          enum:
            - TEXT
            - NUMBER
            - DATE
            - BOOLEAN
          description: Value type of the field
          example: TEXT
    CreateCrmAttributeResult:
      type: object
      properties:
        key:
          type: string
          description: Key derived from the label
          example: lead_source
        label:
          type: string
          description: >-
            Stored label. When the field already existed, this is the label it
            was first created with.
          example: Lead Source
        type:
          type: string
          enum:
            - TEXT
            - NUMBER
            - DATE
            - BOOLEAN
          example: TEXT
        already_existed:
          type: boolean
          description: >-
            `true` when a field with the same key and type already existed and
            nothing was created
          example: false
    ApiError:
      type: object
      properties:
        error:
          type: object
          properties:
            type:
              type: string
            code:
              type: string
            message:
              type: string
            retryable:
              type: boolean
            request_id:
              type: string
            retry_after_seconds:
              type: integer
              nullable: true
  responses:
    ApiValidationError:
      description: Invalid request parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    ApiUnauthorized:
      description: Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    ApiForbidden:
      description: API key lacks the required scope or access to the resource
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    ApiNotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    ApiConflict:
      description: Conflict with existing resource
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    ApiRateLimited:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization

````

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