# Criar campo personalizado

`POST /api/v1/custom-fields`

Cria a definição de um campo personalizado no workspace da chave. Exige `settings.custom_fields`.

## Autenticação

Envie a chave em `Authorization: Bearer pf_live_…`.

## Corpo da requisição

Content-Type: `application/json`

```json
{
  "name": "Segmento",
  "fieldType": "text"
}
```

### Campos

| Campo | Tipo | Obrigatório no objeto | Descrição |
| --- | --- | --- | --- |
| `name` | `string` | Sim | Até 255 caracteres. |
| `slug` | `string` | Não | Gerado a partir do nome quando omitido. Aceita null. Até 255 caracteres. |
| `description` | `string` | Não | Aceita null. Até 1000 caracteres. |
| `placeholder` | `string` | Não | Texto de exemplo exibido no campo vazio do aplicativo. Apenas visual; não é salvo como valor. Aceita null. Até 255 caracteres. |
| `fieldType` | `string` | Sim | `members` apresenta os membros atuais do workspace; o valor salvo é um `userId`, e `options` enviado é descartado. `event` armazena data e hora e cria uma reunião na agenda do responsável, conforme `config.event`. Alterar o campo move a reunião; limpar o campo a exclui. Mover ou excluir a reunião no calendário ou no Google atualiza ou limpa o campo. Disponível apenas para campos de negócio. Valores: text, textarea, number, currency, boolean, date, datetime, select, multi_select, url, email, phone, file_upload, members, event. |
| `options` | `array` | Não | Obrigatório para tipos com opções (`select`, `multi_select`). Ignorado para `members`. Aceita null. |
| `config` | `object` | Não | Configuração por tipo de campo. Para event, informe event com título, duração e configuração da reunião. member_field usa fieldSlug para ler um membro a partir de um campo members do lead. Aceita null. |
| `config.event` | `EventFieldConfig` | Não |  |
| `config.event.title` | `string` | Sim | Até 255 caracteres. |
| `config.event.description` | `string` | Não | Aceita null. Até 2000 caracteres. |
| `config.event.durationMinutes` | `integer` | Sim | Mínimo: 1. Máximo: 1440. |
| `config.event.conferenceMode` | `string` | Não | Valores: none, google_meet, custom_field. Aceita null. |
| `config.event.conferenceFieldSlug` | `string` | Não | Aceita null. |
| `config.event.recordWithBot` | `boolean` | Não | Aceita null. |
| `config.event.attendees` | `array` | Não | Aceita null. |
| `config.event.attendees[].type` | `string` | Não | Valores: lead_contact, deal_co_owner, member, contact, member_field. |
| `config.event.attendees[].userId` | `string` | Não | Aceita null. |
| `config.event.attendees[].contactId` | `string` | Não | Aceita null. |
| `config.event.attendees[].fieldSlug` | `string` | Não | Slug do campo members cujo usuário será convidado. Lido novamente quando o campo mudar. Aceita null. |
| `config.event.attendees[].label` | `string` | Não | Rótulo usado pelo editor; não determina a identidade do convidado. Aceita null. Até 255 caracteres. |
| `isRequired` | `boolean` | Não | Aceita null. |
| `apiOnly` | `boolean` | Não | Quando verdadeiro, os valores do campo no negócio só podem ser alterados pela API pública; o aplicativo exibe o campo como somente leitura. Aceita null. |
| `displayOrder` | `integer` | Não | Aceita null. Mínimo: 0. |
| `section` | `string` | Não | Aceita null. Até 255 caracteres. |
| `entityType` | `string` | Não | Padrão: `deal`. Aceita null. Até 50 caracteres. |
| `visibilityRule` | `object` | Não | Aceita null. |
| `visibilityRule.parentFieldId` | `string` | Sim |  |
| `visibilityRule.values` | `array` | Sim |  |

## Respostas

### 201

Criado

| Campo | Tipo | Obrigatório no objeto | Descrição |
| --- | --- | --- | --- |
| `data` | `CustomFieldDefinition` | Não |  |
| `data.id` | `string` | Não |  |
| `data.entityType` | `string` | Não |  |
| `data.name` | `string` | Não |  |
| `data.slug` | `string` | Não |  |
| `data.description` | `string` | Não | Aceita null. |
| `data.placeholder` | `string` | Não | Texto de exemplo exibido no campo vazio. Aceita null. |
| `data.fieldType` | `string` | Não |  |
| `data.options` | `array` | Não | Opções de seleção. Em `select` e `multi_select`, ficam na definição. Em `members`, são calculadas a partir dos membros do workspace a cada leitura; `value` é o `userId` do membro. Aceita null. |
| `data.options[].value` | `string` | Não |  |
| `data.options[].label` | `string` | Não |  |
| `data.options[].color` | `string` | Não | Aceita null. |
| `data.options[].image` | `string` | Não | URL da foto. Somente para `members`. Aceita null. |
| `data.options[].inactive` | `boolean` | Não | Somente para `members`. Verdadeiro para membro desativado. Ele permanece na lista para resolver nomes de valores anteriores. Não o ofereça para novas escolhas nem altere valores já salvos por causa dessa marcação. |
| `data.config` | `object` | Não | Configuração por tipo de campo. Para event, informe event com título, duração e configuração da reunião. member_field usa fieldSlug para ler um membro a partir de um campo members do lead. Aceita null. |
| `data.config.event` | `EventFieldConfig` | Não |  |
| `data.config.event.title` | `string` | Sim | Até 255 caracteres. |
| `data.config.event.description` | `string` | Não | Aceita null. Até 2000 caracteres. |
| `data.config.event.durationMinutes` | `integer` | Sim | Mínimo: 1. Máximo: 1440. |
| `data.config.event.conferenceMode` | `string` | Não | Valores: none, google_meet, custom_field. Aceita null. |
| `data.config.event.conferenceFieldSlug` | `string` | Não | Aceita null. |
| `data.config.event.recordWithBot` | `boolean` | Não | Aceita null. |
| `data.config.event.attendees` | `array` | Não | Aceita null. |
| `data.config.event.attendees[].type` | `string` | Não | Valores: lead_contact, deal_co_owner, member, contact, member_field. |
| `data.config.event.attendees[].userId` | `string` | Não | Aceita null. |
| `data.config.event.attendees[].contactId` | `string` | Não | Aceita null. |
| `data.config.event.attendees[].fieldSlug` | `string` | Não | Slug do campo members cujo usuário será convidado. Lido novamente quando o campo mudar. Aceita null. |
| `data.config.event.attendees[].label` | `string` | Não | Rótulo usado pelo editor; não determina a identidade do convidado. Aceita null. Até 255 caracteres. |
| `data.isRequired` | `boolean` | Não |  |
| `data.apiOnly` | `boolean` | Não | Valores dos negócios são somente leitura no aplicativo e podem ser alterados por /api/v1. |
| `data.displayOrder` | `integer` | Não |  |
| `data.section` | `string` | Não | Aceita null. |
| `data.pipelineConfig` | `object` | Não | Aceita null. |
| `data.createdAt` | `string` | Não | Formato: date-time. |
| `data.updatedAt` | `string` | Não | Formato: date-time. |
| `data.visibilityRule` | `object` | Não | Aceita null. |
| `data.visibilityRule.parentFieldId` | `string` | Sim |  |
| `data.visibilityRule.values` | `array` | Sim |  |
| `message` | `string` | Não | Aceita null. |

```json
{
  "type": "object",
  "properties": {
    "data": {
      "$ref": "#/components/schemas/CustomFieldDefinition"
    },
    "message": {
      "type": "string",
      "nullable": true
    }
  }
}
```

### 400

Falha de validação dos campos; `fieldErrors` contém os erros.

| Campo | Tipo | Obrigatório no objeto | Descrição |
| --- | --- | --- | --- |
| `error` | `string` | Sim |  |
| `code` | `string` | Sim | Valores: BAD_REQUEST, VALIDATION_ERROR, UNAUTHORIZED, FORBIDDEN, FEATURE_DISABLED, NOT_FOUND, CONFLICT, QUOTA_EXCEEDED, UNPROCESSABLE_ENTITY, INTERNAL_ERROR, SERVICE_UNAVAILABLE. |
| `requestId` | `string` | Sim |  |
| `details` | `string` | Não | Aceita null. |
| `fieldErrors` | `array` | Não | Aceita null. |
| `fieldErrors[].field` | `string` | Não |  |
| `fieldErrors[].message` | `string` | Não |  |

```json
{
  "type": "object",
  "description": "Formato padrão de erro. `details` e `fieldErrors` são omitidos quando ausentes.",
  "properties": {
    "error": {
      "type": "string"
    },
    "code": {
      "type": "string",
      "enum": [
        "BAD_REQUEST",
        "VALIDATION_ERROR",
        "UNAUTHORIZED",
        "FORBIDDEN",
        "FEATURE_DISABLED",
        "NOT_FOUND",
        "CONFLICT",
        "QUOTA_EXCEEDED",
        "UNPROCESSABLE_ENTITY",
        "INTERNAL_ERROR",
        "SERVICE_UNAVAILABLE"
      ]
    },
    "requestId": {
      "type": "string"
    },
    "details": {
      "type": "string",
      "nullable": true
    },
    "fieldErrors": {
      "type": "array",
      "nullable": true,
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  },
  "required": [
    "error",
    "code",
    "requestId"
  ]
}
```

### 401

Chave ausente, malformada, desconhecida, revogada ou expirada, ou membro emissor inativo.

| Campo | Tipo | Obrigatório no objeto | Descrição |
| --- | --- | --- | --- |
| `error` | `string` | Sim |  |
| `code` | `string` | Sim | Valores: BAD_REQUEST, VALIDATION_ERROR, UNAUTHORIZED, FORBIDDEN, FEATURE_DISABLED, NOT_FOUND, CONFLICT, QUOTA_EXCEEDED, UNPROCESSABLE_ENTITY, INTERNAL_ERROR, SERVICE_UNAVAILABLE. |
| `requestId` | `string` | Sim |  |
| `details` | `string` | Não | Aceita null. |
| `fieldErrors` | `array` | Não | Aceita null. |
| `fieldErrors[].field` | `string` | Não |  |
| `fieldErrors[].message` | `string` | Não |  |

```json
{
  "type": "object",
  "description": "Formato padrão de erro. `details` e `fieldErrors` são omitidos quando ausentes.",
  "properties": {
    "error": {
      "type": "string"
    },
    "code": {
      "type": "string",
      "enum": [
        "BAD_REQUEST",
        "VALIDATION_ERROR",
        "UNAUTHORIZED",
        "FORBIDDEN",
        "FEATURE_DISABLED",
        "NOT_FOUND",
        "CONFLICT",
        "QUOTA_EXCEEDED",
        "UNPROCESSABLE_ENTITY",
        "INTERNAL_ERROR",
        "SERVICE_UNAVAILABLE"
      ]
    },
    "requestId": {
      "type": "string"
    },
    "details": {
      "type": "string",
      "nullable": true
    },
    "fieldErrors": {
      "type": "array",
      "nullable": true,
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  },
  "required": [
    "error",
    "code",
    "requestId"
  ]
}
```

### 403

Autenticado, mas sem acesso: falta de permissão (`FORBIDDEN`), recurso desligado no workspace (`FEATURE_DISABLED`) ou tentativa de acessar uma agenda não permitida.

| Campo | Tipo | Obrigatório no objeto | Descrição |
| --- | --- | --- | --- |
| `error` | `string` | Sim |  |
| `code` | `string` | Sim | Valores: BAD_REQUEST, VALIDATION_ERROR, UNAUTHORIZED, FORBIDDEN, FEATURE_DISABLED, NOT_FOUND, CONFLICT, QUOTA_EXCEEDED, UNPROCESSABLE_ENTITY, INTERNAL_ERROR, SERVICE_UNAVAILABLE. |
| `requestId` | `string` | Sim |  |
| `details` | `string` | Não | Aceita null. |
| `fieldErrors` | `array` | Não | Aceita null. |
| `fieldErrors[].field` | `string` | Não |  |
| `fieldErrors[].message` | `string` | Não |  |

```json
{
  "type": "object",
  "description": "Formato padrão de erro. `details` e `fieldErrors` são omitidos quando ausentes.",
  "properties": {
    "error": {
      "type": "string"
    },
    "code": {
      "type": "string",
      "enum": [
        "BAD_REQUEST",
        "VALIDATION_ERROR",
        "UNAUTHORIZED",
        "FORBIDDEN",
        "FEATURE_DISABLED",
        "NOT_FOUND",
        "CONFLICT",
        "QUOTA_EXCEEDED",
        "UNPROCESSABLE_ENTITY",
        "INTERNAL_ERROR",
        "SERVICE_UNAVAILABLE"
      ]
    },
    "requestId": {
      "type": "string"
    },
    "details": {
      "type": "string",
      "nullable": true
    },
    "fieldErrors": {
      "type": "array",
      "nullable": true,
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  },
  "required": [
    "error",
    "code",
    "requestId"
  ]
}
```

### 409

Conflito de estado, como um negócio aberto duplicado para o contato/funil, ou limite do plano atingido (`QUOTA_EXCEEDED`), como na criação de um funil além da cota.

| Campo | Tipo | Obrigatório no objeto | Descrição |
| --- | --- | --- | --- |
| `error` | `string` | Sim |  |
| `code` | `string` | Sim | Valores: BAD_REQUEST, VALIDATION_ERROR, UNAUTHORIZED, FORBIDDEN, FEATURE_DISABLED, NOT_FOUND, CONFLICT, QUOTA_EXCEEDED, UNPROCESSABLE_ENTITY, INTERNAL_ERROR, SERVICE_UNAVAILABLE. |
| `requestId` | `string` | Sim |  |
| `details` | `string` | Não | Aceita null. |
| `fieldErrors` | `array` | Não | Aceita null. |
| `fieldErrors[].field` | `string` | Não |  |
| `fieldErrors[].message` | `string` | Não |  |

```json
{
  "type": "object",
  "description": "Formato padrão de erro. `details` e `fieldErrors` são omitidos quando ausentes.",
  "properties": {
    "error": {
      "type": "string"
    },
    "code": {
      "type": "string",
      "enum": [
        "BAD_REQUEST",
        "VALIDATION_ERROR",
        "UNAUTHORIZED",
        "FORBIDDEN",
        "FEATURE_DISABLED",
        "NOT_FOUND",
        "CONFLICT",
        "QUOTA_EXCEEDED",
        "UNPROCESSABLE_ENTITY",
        "INTERNAL_ERROR",
        "SERVICE_UNAVAILABLE"
      ]
    },
    "requestId": {
      "type": "string"
    },
    "details": {
      "type": "string",
      "nullable": true
    },
    "fieldErrors": {
      "type": "array",
      "nullable": true,
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  },
  "required": [
    "error",
    "code",
    "requestId"
  ]
}
```

### 429

Limite de requisições excedido por workspace ou IP.

| Campo | Tipo | Obrigatório no objeto | Descrição |
| --- | --- | --- | --- |
| `error` | `string` | Sim |  |
| `code` | `string` | Sim | Valores: BAD_REQUEST, VALIDATION_ERROR, UNAUTHORIZED, FORBIDDEN, FEATURE_DISABLED, NOT_FOUND, CONFLICT, QUOTA_EXCEEDED, UNPROCESSABLE_ENTITY, INTERNAL_ERROR, SERVICE_UNAVAILABLE. |
| `requestId` | `string` | Sim |  |
| `details` | `string` | Não | Aceita null. |
| `fieldErrors` | `array` | Não | Aceita null. |
| `fieldErrors[].field` | `string` | Não |  |
| `fieldErrors[].message` | `string` | Não |  |

```json
{
  "type": "object",
  "description": "Formato padrão de erro. `details` e `fieldErrors` são omitidos quando ausentes.",
  "properties": {
    "error": {
      "type": "string"
    },
    "code": {
      "type": "string",
      "enum": [
        "BAD_REQUEST",
        "VALIDATION_ERROR",
        "UNAUTHORIZED",
        "FORBIDDEN",
        "FEATURE_DISABLED",
        "NOT_FOUND",
        "CONFLICT",
        "QUOTA_EXCEEDED",
        "UNPROCESSABLE_ENTITY",
        "INTERNAL_ERROR",
        "SERVICE_UNAVAILABLE"
      ]
    },
    "requestId": {
      "type": "string"
    },
    "details": {
      "type": "string",
      "nullable": true
    },
    "fieldErrors": {
      "type": "array",
      "nullable": true,
      "items": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  },
  "required": [
    "error",
    "code",
    "requestId"
  ]
}
```
