# Crear (/docs/developers/api-reference/departments/create)

## Descripcion general [#descripcion-general]

Este endpoint permite crear uno o varios departamentos dentro de tu organización. Acepta tanto **un objeto** como un **arreglo de hasta 100 objetos**, y la respuesta refleja la forma del cuerpo enviado. El único campo obligatorio por fila es `name`; el resto son opcionales. Los departamentos pueden anidarse mediante `parent_department_number` para formar una jerarquía, y opcionalmente vincularse a un centro de costos vía `cost_center_code` o inline mediante `cost_center`. Una solicitud exitosa devuelve `201` con los departamentos creados, incluyendo los campos generados por el servidor (`id`, `department_number`, `depth`, `created_at`, `updated_at`).

## Endpoint [#endpoint]

`POST https://app.integranom.com/api/v1/departments`

## Solicitud unica — minima [#solicitud-unica--minima]

***

Envía un objeto único con solo `name`. El departamento se crea como raíz (sin padre), sin código, sin centro de costos vinculado y activo por defecto.

```json
{ "name": "Recursos Humanos" }
```

**cURL**

```bash
curl -X POST "https://app.integranom.com/api/v1/departments" \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Recursos Humanos" }'
```

**Respuesta**

```json
{
"id": "ck...",
"department_number": 7,
"parent_id": null,
"depth": 0,
"name": "Recursos Humanos",
"code": null,
"description": null,
"cost_center_id": null,
"is_active": true,
"sort_order": 0,
"created_at": "2026-05-24T10:00:00.000Z",
"updated_at": "2026-05-24T10:00:00.000Z"
}
```

## Solicitud unica — anidada bajo un padre [#solicitud-unica--anidada-bajo-un-padre]

***

Para anidar un departamento bajo otro existente, envía `parent_department_number` con el número del padre. La API calcula `depth` y resuelve el `parent_id` por ti.

```json
{
  "name": "Reclutamiento",
  "code": "RH-REC",
  "description": "Subárea de reclutamiento",
  "parent_department_number": 1,
  "sort_order": 10
}
```

**cURL**

```bash
curl -X POST "https://app.integranom.com/api/v1/departments" \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
  "name": "Reclutamiento",
  "code": "RH-REC",
  "description": "Subárea de reclutamiento",
  "parent_department_number": 1,
  "sort_order": 10
}'
```

**Respuesta**

```json
{
"id": "ck...",
"department_number": 8,
"parent_id": "ck...",
"depth": 1,
"name": "Reclutamiento",
"code": "RH-REC",
"description": "Subárea de reclutamiento",
"cost_center_id": null,
"is_active": true,
"sort_order": 10,
"created_at": "2026-05-24T10:00:00.000Z",
"updated_at": "2026-05-24T10:00:00.000Z"
}
```

## Solicitud unica — con centro de costos inline [#solicitud-unica--con-centro-de-costos-inline]

***

Cuando el departamento se vincula a un centro de costos (vía `cost_center_code` o inline con `cost_center`), el **centro de costos es la fuente de verdad** para los siguientes campos del departamento: `name`, `code`, `description`, `is_active`, `sort_order`. Cualquier valor que el usuario envíe para esos campos se ignora silenciosamente y el departamento se escribe con los valores del CC.

Observa la respuesta: aunque se envió `"name": "Ventas"` y `"code": "VEN"`, el departamento se guardó con `"name": "Centro de costos Ventas"` y `"code": "CC-VEN"` porque esos son los valores del centro de costos.

```json
{
  "name": "Ventas",
  "code": "VEN",
  "parent_department_number": 1,
  "cost_center": {
    "code": "CC-VEN",
    "name": "Centro de costos Ventas",
    "is_active": true
  }
}
```

**cURL**

```bash
curl -X POST "https://app.integranom.com/api/v1/departments" \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
  "name": "Ventas",
  "code": "VEN",
  "parent_department_number": 1,
  "cost_center": {
    "code": "CC-VEN",
    "name": "Centro de costos Ventas",
    "is_active": true
  }
}'
```

**Respuesta**

```json
{
"id": "ck...",
"department_number": 5,
"parent_id": "ck...",
"depth": 1,
"name": "Centro de costos Ventas",
"code": "CC-VEN",
"description": null,
"cost_center_id": "ck...",
"is_active": true,
"sort_order": 0,
"created_at": "2026-05-24T10:00:00.000Z",
"updated_at": "2026-05-24T10:00:00.000Z"
}
```

## Solicitud por lote (1–100 departamentos) [#solicitud-por-lote-1100-departamentos]

***

Envía un **arreglo** de hasta 100 departamentos en el mismo endpoint, el modo lote se activa al enviar un arreglo como cuerpo. Si **cualquier** fila falla la validación, **ningún** departamento se crea y la respuesta lista los problemas por fila.

**Referencias entre filas no permitidas.** Una fila no puede usar `parent_department_number` para apuntar a otra fila del mismo lote — los padres deben existir antes de la solicitud. Para construir árboles de varios niveles, crea los nodos raíz en una solicitud y los hijos en una segunda. De la misma forma, un `cost_center` inline no puede compartirse entre filas: cada fila crea su propio CC.

```json
[
  { "name": "Marketing", "code": "MKT" },
  { "name": "Finanzas", "code": "FIN", "parent_department_number": 1 }
]
```

**cURL**

```bash
curl -X POST "https://app.integranom.com/api/v1/departments" \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '[
  { "name": "Marketing", "code": "MKT" },
  { "name": "Finanzas", "code": "FIN", "parent_department_number": 1 }
]'
```

**Respuesta**

```json
{
"summary": { "total": 2, "created": 2 },
"created": [
  {
    "id": "ck...",
    "department_number": 6,
    "parent_id": null,
    "depth": 0,
    "name": "Marketing",
    "code": "MKT",
    "description": null,
    "cost_center_id": null,
    "is_active": true,
    "sort_order": 0,
    "created_at": "2026-05-24T10:00:00.000Z",
    "updated_at": "2026-05-24T10:00:00.000Z"
  },
  {
    "id": "ck...",
    "department_number": 7,
    "parent_id": "ck...",
    "depth": 1,
    "name": "Finanzas",
    "code": "FIN",
    "description": null,
    "cost_center_id": null,
    "is_active": true,
    "sort_order": 0,
    "created_at": "2026-05-24T10:00:00.000Z",
    "updated_at": "2026-05-24T10:00:00.000Z"
  }
]
}
```

## Reglas de los campos [#reglas-de-los-campos]

| Campo                      | Tipo             | Requerido | Notas                                                                                                                                                                                          |
| -------------------------- | ---------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                     | string           | Sí        | No vacío tras recortar espacios. (Sobrescrito silenciosamente si el departamento se vincula a un CC.)                                                                                          |
| `code`                     | string           | No        | ≤ 60 caracteres, se almacena en mayúsculas, único por organización. (Sobrescrito silenciosamente si el departamento se vincula a un CC.)                                                       |
| `description`              | string           | No        | Texto libre. (Sobrescrito silenciosamente si el departamento se vincula a un CC.)                                                                                                              |
| `parent_department_number` | integer positivo | No        | Debe ser el `department_number` de un departamento existente en la misma organización. No se permiten referencias dentro del lote.                                                             |
| `cost_center_code`         | string           | No        | Código de un CC existente; se almacena en mayúsculas. Mutuamente excluyente con `cost_center`.                                                                                                 |
| `cost_center`              | object           | No        | Crea un CC nuevo y vincula este departamento a él (forma abajo). Mutuamente excluyente con `cost_center_code`. En modo lote, cada fila crea su propio CC — no se pueden compartir entre filas. |
| `is_active`                | boolean          | No        | Por defecto `true`. (Sobrescrito silenciosamente si el departamento se vincula a un CC.)                                                                                                       |
| `sort_order`               | integer ≥ 0      | No        | Por defecto `0`. (Sobrescrito silenciosamente si el departamento se vincula a un CC.)                                                                                                          |

### Forma de `cost_center` (creación inline) [#forma-de-cost_center-creación-inline]

| Campo                     | Tipo        | Requerido | Notas                                                    |
| ------------------------- | ----------- | --------- | -------------------------------------------------------- |
| `code`                    | string      | Sí        | Se almacena en mayúsculas, ≤ 60, único por organización. |
| `name`                    | string      | Sí        | No vacío tras recortar espacios.                         |
| `description`             | string      | No        |                                                          |
| `parent_cost_center_code` | string      | No        | Código de un CC existente en la organización.            |
| `sort_order`              | integer ≥ 0 | No        | Por defecto `0`.                                         |

### Espejo de campos con el centro de costos [#espejo-de-campos-con-el-centro-de-costos]

Cuando el departamento se vincula a un centro de costos (al crear, sea vía `cost_center_code` o `cost_center`), el CC es dueño de estos campos en el departamento: `name`, `code`, `description`, `sort_order`. Los valores que el usuario envíe para esos campos se ignoran y el departamento se escribe con los valores del CC.

## Forma de las respuestas [#forma-de-las-respuestas]

### `201` — solicitud única [#201--solicitud-única]

Cuando el cuerpo es **un objeto**, la respuesta es el objeto del departamento creado.

```json
{
  "id": "ck...",
  "department_number": 5,
  "parent_id": "ck...",
  "depth": 1,
  "name": "Ventas",
  "code": "VEN",
  "description": null,
  "cost_center_id": null,
  "is_active": true,
  "sort_order": 0,
  "created_at": "2026-05-24T10:00:00.000Z",
  "updated_at": "2026-05-24T10:00:00.000Z"
}
```

### `201` — solicitud por lote [#201--solicitud-por-lote]

Cuando el cuerpo es **un arreglo**, la respuesta envuelve los resultados en `summary` + `created[]`.

```json
{
  "summary": { "total": 2, "created": 2 },
  "created": [
    { "id": "ck...", "department_number": 6, "...": "..." },
    { "id": "ck...", "department_number": 7, "...": "..." }
  ]
}
```

## Errores [#errores]

### `400` — validación fallida (solicitud única) [#400--validación-fallida-solicitud-única]

Para fallas de validación de campos, `errors` es un objeto indexado por campo:

```json
{
  "message": "Validation failed.",
  "errors": { "name": ["Ingresa el nombre."] }
}
```

### `400` — validación fallida (solicitud por lote) [#400--validación-fallida-solicitud-por-lote]

Reporte por fila. **Ningún** departamento del lote fue creado.

```json
{
  "message": "Validation failed for 2 department(s). No departments were created.",
  "summary": { "total": 3, "with_errors": 2 },
  "errors": [
    {
      "index": 0,
      "department": { "name": "Ventas", "code": "VEN" },
      "issues": [
        {
          "field": "parent_department_number",
          "code": "PARENT_DEPARTMENT_NOT_FOUND",
          "message": "No department with number '99' in this organization."
        }
      ]
    },
    {
      "index": 2,
      "department": { "name": "Compras", "code": "VEN" },
      "issues": [
        {
          "field": "code",
          "code": "DUPLICATE_CODE_IN_BATCH",
          "message": "Code 'VEN' appears multiple times in this batch."
        }
      ]
    }
  ]
}
```

* `index` — posición 0-based de la fila que falló dentro del arreglo enviado.
* `department.name` / `department.code` — extraídos de tu entrada para que identifiques la fila sin contar.
* `issues[]` — todos los problemas de esa fila listados juntos para corregirlos antes de reintentar.

### `409` — condición de carrera [#409--condición-de-carrera]

Se devuelve con el código `CONCURRENT_MODIFICATION` cuando otra solicitud reclama un `code` (o modifica un CC referenciado) entre el momento en que validamos el tuyo y el momento en que escribimos. En modo lote, la transacción completa hace rollback — ningún departamento es creado. Reintenta la misma solicitud.

## Vocabulario de códigos de error [#vocabulario-de-códigos-de-error]

Estos códigos aparecen dentro de `issues[].code` (o como `code` en el cuerpo de error en single) y son estables — tu cliente puede ramificar lógica con base en ellos:

| Codigo                                | Significado                                                            |
| ------------------------------------- | ---------------------------------------------------------------------- |
| `INVALID_INPUT`                       | Falla genérica de validación de campos (formato, longitud, tipo).      |
| `PARENT_DEPARTMENT_NOT_FOUND`         | `parent_department_number` no coincide con un departamento existente.  |
| `COST_CENTER_NOT_FOUND`               | `cost_center_code` no coincide con un CC existente.                    |
| `COST_CENTER_PARENT_NOT_FOUND`        | `cost_center.parent_cost_center_code` no coincide con un CC existente. |
| `DUPLICATE_CODE`                      | `code` ya existe en la base de datos para esta organización.           |
| `DUPLICATE_CODE_IN_BATCH`             | Dos o más filas del lote envían el mismo `code`.                       |
| `DUPLICATE_COST_CENTER_CODE`          | El `cost_center.code` inline ya existe en la base de datos.            |
| `DUPLICATE_COST_CENTER_CODE_IN_BATCH` | Dos o más filas envían el mismo `cost_center.code` inline.             |
| `CONCURRENT_MODIFICATION`             | Señal de reintento por condición de carrera (respuesta `409`).         |