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

## Descripcion general [#descripcion-general]

Este endpoint permite crear uno o varios empleados 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. Cada empleado se crea vinculado a la `legal_entity_number` enviada. Una solicitud exitosa devuelve `201` con los empleados creados como un objeto **plano** que incluye los datos personales, los de su empleo (estatus, fechas, asignaciones y compensación) y los campos generados por el servidor (`employee_number`, `created_at`, `updated_at`).

**Estatus y alta de nómina.** Si omites `activate`, el empleado solo se crea con estatus `active` cuando está **listo para nómina**, es decir, cuando la fila incluye `legal_entity_number`, `rfc`, `curp`, `postal_code` (o `home_postal_code` si `fiscal_address_same_as_home` es `true`), `work_center_state_code`, `daily_base_salary`, `regimen_fiscal`, `work_shift_type`, `payroll_calendar_number`, `contract_number`, y además `imss_number`, `imss_worker_type` e `imss_work_schedule` si `contributes_to_imss` es `true`. Si falta alguno, se crea como `pending` (Sin alta en nómina). Con `activate: true`, un empleado que no está listo se rechaza con `400` `ACTIVATION_INCOMPLETE` y la lista de datos faltantes; envía `activate: false` para forzar `pending`. Si el alta cae en periodos de nómina ya **cerrados**, la llamada se rechaza con `409` `RETRO_CONFIRMATION_REQUIRED` (con `retro_periods`); reenvíala con `confirm_retro: true` y cada periodo se paga con un ajuste retroactivo en la siguiente nómina. Cuando capturas `daily_base_salary`, se registra automáticamente la primera fila del historial de sueldos.

En modo lote, si **cualquier** fila falla la validación, **ningún** empleado se crea — la respuesta lista los problemas por fila para corregirlos en una sola pasada.

Si envías `termination_date` en una fila, el empleado se crea **dado de baja**, útil al cargar el historial de alguien que ya se fue. La fecha no puede ser posterior a hoy ni anterior a `hire_date`, y la fila no puede traer `activate: true` (sino, `400`). Un empleado creado dado de baja nunca pide `confirm_retro` ni genera ajustes retroactivos. Si `contributes_to_imss` es `true`, `employer_registration` se vuelve obligatorio en la misma fila (sino, `400`).

**Movimientos IMSS.** Cada empleado creado que aporta al IMSS genera su alta en Movimientos IMSS, y su baja si la fila trae `termination_date`. Envía `already_registered_with_imss: true` cuando el alta ya se presentó ante el IMSS fuera de la plataforma, por ejemplo al migrar desde otro sistema: queda registrada como ya presentada, sin fecha límite y sin SBC calculado. Por defecto es `false` y queda pendiente de presentar. La baja sigue `termination_already_registered_with_imss`; si lo omites, toma la misma respuesta que el alta.

**Tipo de trabajador.** `worker_type` dice qué es la persona para efectos estatutarios: `subordinate` (por defecto), `asimilado` u `honorarios`. No se infiere del tipo de contrato SAT. Un asimilado o un trabajador por honorarios recibe sueldo e ISR sin subsidio, sin IMSS, sin SBC ni prestaciones de ley, así que `contributes_to_imss` debe ser `false` para ellos (sino, `400`). Por la misma razón no llevan `imss_number`, `employer_registration` ni `seniority_date`: enviar cualquiera de ellos con un `worker_type` distinto de `subordinate` responde `400` en ese campo.

**Horario de trabajo.** El horario se asigna al empleado, no a su contrato: dos personas con el mismo contrato pueden tener horarios distintos. Envía `work_schedule_number` para un horario semanal fijo **o** `work_schedule_bundle_number` para una rotación — nunca ambos (`400`). Con una rotación puedes indicar `work_schedule_bundle_start_step` para escalonar al empleado dentro del ciclo (una cuadrilla en matutino mientras otra va en nocturno); si lo omites, arranca en el primer paso de la rotación, que es lo que lo mantiene sincronizado con ella. Un `work_schedule_bundle_start_step` sin rotación en el mismo cuerpo se rechaza con `400`. Si no envías ninguno de los dos, el empleado sigue el horario predeterminado de la organización.

> **Nota sobre los números de horario:** los horarios y las rotaciones aún no se exponen como endpoint propio en la API; utiliza el número visible en **Configuración → Tiempo y Acceso → Horarios**.

**Campos personalizados.** Los valores de campos personalizados se envían como **claves planas en la raíz del cuerpo del empleado**, junto a `first_name`, `rfc`, etc. La clave es el `key` de la definición (gestionada en [Campos personalizados → Empleados](/docs/developers/api-reference/custom-fields/employees/list)) y el valor debe ser compatible con el `type` de la definición. Cualquier definición activa marcada con `is_required_for_create: true` debe enviarse en **cada** fila — si falta, la fila falla con `CUSTOM_FIELD_REQUIRED`.

## Endpoint [#endpoint]

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

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

***

Envía solo los seis campos obligatorios. Al no incluir la compensación completa, el empleado se crea como `pending` (Sin alta en nómina), vinculado a la razón social indicada, sin puesto, sucursal, departamento ni centro de costos. `contributes_to_imss` toma `false` por defecto y `is_included_in_payroll_calculations` toma `true`.

```json
{
  "first_name": "María",
  "paternal_last_name": "González",
  "rfc": "GOPM900101AB1",
  "curp": "GOPM900101MDFNRR07",
  "legal_entity_number": 1,
  "hire_date": "2026-01-15",
  "work_center_state_code": "CMX"
}
```

**cURL**

```bash
curl -X POST "https://app.integranom.com/api/v1/employees" \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
  "first_name": "María",
  "paternal_last_name": "González",
  "rfc": "GOPM900101AB1",
  "curp": "GOPM900101MDFNRR07",
  "legal_entity_number": 1,
  "hire_date": "2026-01-15",
  "work_center_state_code": "CMX"
}'
```

**Respuesta**

```json
{
"employee_number": 5,
"internal_number": null,
"first_name": "María",
"middle_name": null,
"paternal_last_name": "González",
"maternal_last_name": null,
"gender": null,
"birth_date": null,
"birth_country": null,
"birth_state": null,
"birth_state_code": null,
"birth_municipality_code": null,
"birth_city": null,
"birth_place": null,
"nationality": null,
"phone_number": null,
"secondary_phone_number": null,
"rfc": "GOPM900101AB1",
"curp": "GOPM900101MDFNRR07",
"postal_code": null,
"work_center_state_code": "CMX",
"home_street": null,
"home_exterior_number": null,
"home_interior_number": null,
"home_neighborhood": null,
"home_municipality_code": null,
"home_city": null,
"home_state_code": null,
"home_postal_code": null,
"fiscal_address_same_as_home": false,
"domicile_state_code": null,
"fiscal_street": null,
"fiscal_exterior_number": null,
"fiscal_interior_number": null,
"fiscal_neighborhood": null,
"fiscal_municipality_code": null,
"fiscal_city": null,
"bank": null,
"clabe": null,
"account_number": null,
"card_number": null,
"notes": null,
"legal_entity_number": 1,
"status": "pending",
"hire_date": "2026-01-15T00:00:00.000Z",
"seniority_date": null,
"termination_date": null,
"job_position_code": null,
"branch_code": null,
"department_code": null,
"cost_center_code": null,
"employer_registration": null,
"imss_number": null,
"contributes_to_imss": false,
"worker_type": "subordinate",
"minimum_wage_zone": "general",
"imss_worker_type": null,
"imss_work_schedule": null,
"salary_type": null,
"is_unionized": false,
"receives_annual_isr_adjustment": true,
"opts_into_annual_isr_adjustment": false,
"is_included_in_payroll_calculations": true,
"daily_base_salary": null,
"regimen_fiscal": null,
"work_shift_type": null,
"payroll_calendar_number": null,
"contract_number": null,
"work_schedule_number": null,
"work_schedule_bundle_number": null,
"work_schedule_bundle_start_step": null,
"organizational_units": [],
"created_at": "2026-05-25T10:00:00.000Z",
"updated_at": "2026-05-25T10:00:00.000Z"
}
```

## Solicitud unica — con datos laborales + campos personalizados [#solicitud-unica--con-datos-laborales--campos-personalizados]

***

Para asignar puesto, departamento, sucursal, centro de costos o registro patronal al empleado, envía los códigos correspondientes. Al incluir además la compensación completa (`postal_code` —o `home_postal_code` con `fiscal_address_same_as_home: true`—, `daily_base_salary`, `regimen_fiscal`, `work_shift_type`, `payroll_calendar_number`, `contract_number`), el empleado queda **listo para nómina** y se crea con estatus `active`. Cuando `contributes_to_imss` es `true`, `employer_registration` es obligatorio. Los valores de campos personalizados van como **claves planas en la raíz del cuerpo**, utilizando el `key` de la definición.

```json
{
  "first_name": "María",
  "paternal_last_name": "González",
  "maternal_last_name": "Pérez",
  "rfc": "GOPM900101AB1",
  "curp": "GOPM900101MDFNRR07",
  "legal_entity_number": 1,
  "hire_date": "2026-01-15",
  "work_center_state_code": "CMX",
  "postal_code": "06000",
  "department_code": "VEN",
  "job_position_code": "GER-VEN",
  "branch_code": "CDMX",
  "cost_center_code": "CC01",
  "contributes_to_imss": true,
  "already_registered_with_imss": false,
  "employer_registration": "Y6712345678",
  "imss_number": "12345678903",
  "daily_base_salary": 500,
  "regimen_fiscal": "02",
  "work_shift_type": "01",
  "payroll_calendar_number": 2,
  "contract_number": 5,
  "work_schedule_number": 3,
  "work_schedule_bundle_number": null,
  "work_schedule_bundle_start_step": null,
  "organizational_units": [10],
  "shirt_size": "M",
  "fit_for_duty": true,
  "years_experience": 7
}
```

**cURL**

```bash
curl -X POST "https://app.integranom.com/api/v1/employees" \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
  "first_name": "María",
  "paternal_last_name": "González",
  "maternal_last_name": "Pérez",
  "rfc": "GOPM900101AB1",
  "curp": "GOPM900101MDFNRR07",
  "legal_entity_number": 1,
  "hire_date": "2026-01-15",
  "work_center_state_code": "CMX",
  "postal_code": "06000",
  "department_code": "VEN",
  "job_position_code": "GER-VEN",
  "branch_code": "CDMX",
  "cost_center_code": "CC01",
  "contributes_to_imss": true,
  "already_registered_with_imss": false,
  "employer_registration": "Y6712345678",
  "imss_number": "12345678903",
  "daily_base_salary": 500,
  "regimen_fiscal": "02",
  "work_shift_type": "01",
  "payroll_calendar_number": 2,
  "contract_number": 5,
  "work_schedule_number": 3,
  "work_schedule_bundle_number": null,
  "work_schedule_bundle_start_step": null,
  "organizational_units": [10],
  "shirt_size": "M",
  "fit_for_duty": true,
  "years_experience": 7
}'
```

**Respuesta**

```json
{
"employee_number": 5,
"internal_number": null,
"first_name": "María",
"middle_name": null,
"paternal_last_name": "González",
"maternal_last_name": "Pérez",
"gender": null,
"birth_date": null,
"birth_country": null,
"birth_state": null,
"birth_state_code": null,
"birth_municipality_code": null,
"birth_city": null,
"birth_place": null,
"nationality": null,
"phone_number": null,
"secondary_phone_number": null,
"rfc": "GOPM900101AB1",
"curp": "GOPM900101MDFNRR07",
"postal_code": "06000",
"work_center_state_code": "CMX",
"home_street": null,
"home_exterior_number": null,
"home_interior_number": null,
"home_neighborhood": null,
"home_municipality_code": null,
"home_city": null,
"home_state_code": null,
"home_postal_code": null,
"fiscal_address_same_as_home": false,
"domicile_state_code": null,
"fiscal_street": null,
"fiscal_exterior_number": null,
"fiscal_interior_number": null,
"fiscal_neighborhood": null,
"fiscal_municipality_code": null,
"fiscal_city": null,
"bank": null,
"clabe": null,
"account_number": null,
"card_number": null,
"notes": null,
"legal_entity_number": 1,
"status": "active",
"hire_date": "2026-01-15T00:00:00.000Z",
"seniority_date": null,
"termination_date": null,
"job_position_code": "GER-VEN",
"branch_code": "CDMX",
"department_code": "VEN",
"cost_center_code": "CC01",
"employer_registration": "Y6712345678",
"imss_number": "12345678903",
"contributes_to_imss": true,
"worker_type": "subordinate",
"minimum_wage_zone": "general",
"imss_worker_type": "permanent",
"imss_work_schedule": "full",
"salary_type": null,
"is_unionized": false,
"receives_annual_isr_adjustment": true,
"opts_into_annual_isr_adjustment": false,
"is_included_in_payroll_calculations": true,
"daily_base_salary": "500.0000",
"regimen_fiscal": "02",
"work_shift_type": "01",
"payroll_calendar_number": 2,
"contract_number": 5,
"work_schedule_number": 3,
"work_schedule_bundle_number": null,
"work_schedule_bundle_start_step": null,
"organizational_units": [
  { "organizational_unit_number": 10, "organizational_unit_type_key": "region" }
],
"created_at": "2026-05-25T10:00:00.000Z",
"updated_at": "2026-05-25T10:00:00.000Z"
}
```

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

***

Envía un **arreglo** de hasta 100 empleados en el mismo endpoint. Si **cualquier** fila falla la validación, **ningún** empleado se crea y la respuesta lista los problemas por fila.

```json
[
  {
    "first_name": "María",
    "paternal_last_name": "González",
    "rfc": "GOPM900101AB1",
    "curp": "GOPM900101MDFNRR07",
    "legal_entity_number": 1,
    "hire_date": "2026-01-15",
    "work_center_state_code": "CMX"
  },
  {
    "first_name": "Juan",
    "paternal_last_name": "Pérez",
    "rfc": "PEXJ850715XY2",
    "curp": "PEXJ850715HDFRRN09",
    "legal_entity_number": 1,
    "hire_date": "2026-01-15",
    "work_center_state_code": "CMX"
  }
]
```

**cURL**

```bash
curl -X POST "https://app.integranom.com/api/v1/employees" \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '[
  {
    "first_name": "María",
    "paternal_last_name": "González",
    "rfc": "GOPM900101AB1",
    "curp": "GOPM900101MDFNRR07",
    "legal_entity_number": 1,
    "hire_date": "2026-01-15",
    "work_center_state_code": "CMX"
  },
  {
    "first_name": "Juan",
    "paternal_last_name": "Pérez",
    "rfc": "PEXJ850715XY2",
    "curp": "PEXJ850715HDFRRN09",
    "legal_entity_number": 1,
    "hire_date": "2026-01-15",
    "work_center_state_code": "CMX"
  }
]'
```

**Respuesta**

```json
{
"summary": { "total": 2, "created": 2 },
"created": [
  {
    "employee_number": 6,
    "first_name": "María",
    "paternal_last_name": "González",
    "status": "pending",
    "legal_entity_number": 1,
    "...": "resto de campos planos como en la respuesta única"
  },
  {
    "employee_number": 7,
    "first_name": "Juan",
    "paternal_last_name": "Pérez",
    "status": "pending",
    "legal_entity_number": 1,
    "...": "..."
  }
]
}
```

## Campos obligatorios [#campos-obligatorios]

| Campo                    | Tipo                | Notas                                                                                                                         |
| ------------------------ | ------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `first_name`             | string              | Mínimo 1 carácter tras recortar.                                                                                              |
| `paternal_last_name`     | string              | Mínimo 1 carácter tras recortar.                                                                                              |
| `rfc`                    | string              | 12 o 13 caracteres. Se almacena en mayúsculas. Único por organización.                                                        |
| `curp`                   | string              | Exactamente 18 caracteres. Se almacena en mayúsculas. Único por organización.                                                 |
| `legal_entity_number`    | integer positivo    | Debe corresponder a una razón social existente en la organización. Define la razón social del empleado.                       |
| `hire_date`              | string `YYYY-MM-DD` | Fecha de alta del empleado.                                                                                                   |
| `work_center_state_code` | string              | Entidad del centro de trabajo, clave SAT c\_Estado de 3 letras (por ejemplo `CMX`). Define la tasa del impuesto sobre nómina. |

## Campos opcionales — datos personales del empleado [#campos-opcionales--datos-personales-del-empleado]

| Campo                         | Tipo                                | Notas                                                                                                                                                                                                                                                                                                                            |
| ----------------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `middle_name`                 | string                              |                                                                                                                                                                                                                                                                                                                                  |
| `maternal_last_name`          | string                              |                                                                                                                                                                                                                                                                                                                                  |
| `gender`                      | `male` \| `female` \| `unspecified` |                                                                                                                                                                                                                                                                                                                                  |
| `birth_date`                  | string `YYYY-MM-DD`                 |                                                                                                                                                                                                                                                                                                                                  |
| `birth_country`               | string                              |                                                                                                                                                                                                                                                                                                                                  |
| `birth_state`                 | string                              | Nombre del estado de nacimiento. Se acepta por compatibilidad: si coincide con un estado del catálogo se guarda su clave; si no, se conserva el texto. Prefiere `birth_state_code`.                                                                                                                                              |
| `birth_city`                  | string                              | Nombre del municipio de nacimiento. Se acepta por compatibilidad: si coincide con un municipio del estado de nacimiento se guarda su clave; si no, se conserva el texto. Prefiere `birth_municipality_code`.                                                                                                                     |
| `birth_state_code`            | string                              | Estado de nacimiento, clave SAT c\_Estado de 3 letras (por ejemplo `JAL`).                                                                                                                                                                                                                                                       |
| `birth_municipality_code`     | string                              | Municipio de nacimiento, clave INEGI de 3 dígitos dentro de `birth_state_code` (por ejemplo `120`).                                                                                                                                                                                                                              |
| `birth_place`                 | string                              |                                                                                                                                                                                                                                                                                                                                  |
| `nationality`                 | string                              | Nacionalidad en gentilicio, del catálogo de nacionalidades (por ejemplo `Mexicana`). No distingue mayúsculas, acentos ni género, y acepta el nombre del país, la forma en inglés o la clave de tres letras: `MEXICANO`, `México` y `MEX` se guardan como `Mexicana`. Un valor fuera del catálogo responde `INVALID_NATIONALITY`. |
| `phone_number`                | string                              | Teléfono del empleado con clave de país y sin espacios, por ejemplo `+529611234567`.                                                                                                                                                                                                                                             |
| `secondary_phone_number`      | string                              | Teléfono secundario. Mismo formato que `phone_number`.                                                                                                                                                                                                                                                                           |
| `postal_code`                 | string `#####`                      | Código postal de 5 dígitos del domicilio fiscal (el de la Constancia de Situación Fiscal), que es el que valida el CFDI. Cuenta para la preparación de nómina. Se ignora si `fiscal_address_same_as_home` es `true`.                                                                                                             |
| `home_street`                 | string                              | Calle del domicilio real (donde vive el empleado). Independiente del domicilio fiscal.                                                                                                                                                                                                                                           |
| `home_exterior_number`        | string                              | Número exterior del domicilio real.                                                                                                                                                                                                                                                                                              |
| `home_interior_number`        | string                              | Número interior del domicilio real.                                                                                                                                                                                                                                                                                              |
| `home_neighborhood`           | string                              | Colonia del domicilio real.                                                                                                                                                                                                                                                                                                      |
| `home_municipality_code`      | string                              | Municipio o alcaldía del domicilio real, clave INEGI de 3 dígitos dentro de `home_state_code` (por ejemplo `039`). La respuesta devuelve además `home_city` con el nombre.                                                                                                                                                       |
| `home_city`                   | string                              | Nombre del municipio o alcaldía. Se acepta por compatibilidad: si coincide con un municipio de `home_state_code` se guarda su clave; si no, se conserva el texto. Prefiere `home_municipality_code`.                                                                                                                             |
| `home_state_code`             | string                              | Estado del domicilio real, clave SAT c\_Estado de 3 letras (por ejemplo `NLE`).                                                                                                                                                                                                                                                  |
| `home_postal_code`            | string `#####`                      | Código postal de 5 dígitos del domicilio real. Solo cuenta para la preparación de nómina si `fiscal_address_same_as_home` es `true`.                                                                                                                                                                                             |
| `fiscal_address_same_as_home` | boolean                             | `true` si el domicilio fiscal es el mismo que el real: se copia del domicilio real (`home_*`) y se ignoran `postal_code`, `domicile_state_code` y los `fiscal_*` enviados. Si se omite, es `false`.                                                                                                                              |
| `domicile_state_code`         | string                              | Estado del domicilio fiscal, clave SAT c\_Estado de 3 letras (por ejemplo `NLE`).                                                                                                                                                                                                                                                |
| `fiscal_street`               | string                              | Calle del domicilio fiscal.                                                                                                                                                                                                                                                                                                      |
| `fiscal_exterior_number`      | string                              | Número exterior del domicilio fiscal.                                                                                                                                                                                                                                                                                            |
| `fiscal_interior_number`      | string                              | Número interior del domicilio fiscal.                                                                                                                                                                                                                                                                                            |
| `fiscal_neighborhood`         | string                              | Colonia del domicilio fiscal.                                                                                                                                                                                                                                                                                                    |
| `fiscal_municipality_code`    | string                              | Municipio o alcaldía del domicilio fiscal, clave INEGI de 3 dígitos dentro de `domicile_state_code`. La respuesta devuelve además `fiscal_city` con el nombre.                                                                                                                                                                   |
| `fiscal_city`                 | string                              | Nombre del municipio o alcaldía del domicilio fiscal. Se acepta por compatibilidad: si coincide con un municipio de `domicile_state_code` se guarda su clave; si no, se conserva el texto. Prefiere `fiscal_municipality_code`.                                                                                                  |
| `internal_number`             | string                              | Número interno que la organización asigna por su cuenta (por ejemplo, el de una nómina anterior). Texto libre, único en la organización sin distinguir mayúsculas: si otro empleado ya lo tiene, la respuesta es `409` con `DUPLICATE_INTERNAL_NUMBER`.                                                                          |
| `bank`                        | string                              | Nombre del banco, máximo 60 caracteres. Texto libre; utiliza el nombre del catálogo SAT c\_Banco para que coincida con el selector de la plataforma.                                                                                                                                                                             |
| `clabe`                       | string `18 dígitos`                 | CLABE interbancaria. Se valida el dígito verificador.                                                                                                                                                                                                                                                                            |
| `account_number`              | string                              | Número de cuenta, solo dígitos: máximo 12 si `bank` es BANREGIO, máximo 11 para cualquier otro banco. Sin una `clabe` válida, requiere `bank` (sino `400` en `bank`), porque el recibo nombra el banco.                                                                                                                          |
| `card_number`                 | string `16 dígitos`                 | Número de tarjeta.                                                                                                                                                                                                                                                                                                               |
| `notes`                       | string                              | Notas libres.                                                                                                                                                                                                                                                                                                                    |

## Campos opcionales — datos laborales del empleado [#campos-opcionales--datos-laborales-del-empleado]

| Campo                                      | Tipo                                                                                                                          | Notas                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `job_position_code`                        | string                                                                                                                        | Código de un puesto activo en la organización.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `branch_code`                              | string                                                                                                                        | Código de una sucursal activa.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `department_code`                          | string                                                                                                                        | Código de un departamento activo.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `cost_center_code`                         | string                                                                                                                        | Código de un centro de costos activo.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `employer_registration`                    | string                                                                                                                        | Número de registro patronal IMSS, dentro de la `legal_entity_number` de la fila. Solo para `subordinate` (sino `400`).                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `seniority_date`                           | string `YYYY-MM-DD`                                                                                                           | Si se omite, el empleado no lleva fecha de antigüedad. Solo para `subordinate` (sino `400`). No puede ser posterior a hoy en la hora de la Ciudad de México (sino `400`).                                                                                                                                                                                                                                                                                                                                                                      |
| `termination_date`                         | string `YYYY-MM-DD`                                                                                                           | Si se envía, el empleado se crea como dado de baja (uso histórico). No puede ser posterior a hoy ni anterior a `hire_date`, ni enviarse con `activate: true`.                                                                                                                                                                                                                                                                                                                                                                                  |
| `imss_number`                              | string                                                                                                                        | NSS de 11 dígitos. Se valida el dígito verificador. Solo para `subordinate` (sino `400`).                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `contributes_to_imss`                      | boolean                                                                                                                       | Por defecto `false`. Cuando es `true`, `employer_registration` es obligatorio (sino `400`). Debe ser `false` cuando `worker_type` no es `subordinate`.                                                                                                                                                                                                                                                                                                                                                                                         |
| `already_registered_with_imss`             | boolean                                                                                                                       | Por defecto `false`. Con `true`, el alta en Movimientos IMSS (y la baja, si la fila trae `termination_date` sin `termination_already_registered_with_imss`) se registra como ya presentada ante el IMSS fuera de la plataforma: no queda pendiente ni se calcula su SBC. Con `false`, el movimiento queda pendiente de presentar. Solo tiene efecto cuando `contributes_to_imss` es `true`.                                                                                                                                                    |
| `termination_already_registered_with_imss` | boolean                                                                                                                       | Solo con `termination_date`. Con `true`, la baja se registra como ya presentada ante el IMSS; con `false`, queda pendiente de presentar. Si se omite, toma el valor de `already_registered_with_imss`.                                                                                                                                                                                                                                                                                                                                         |
| `worker_type`                              | `subordinate` \| `asimilado` \| `honorarios`                                                                                  | Por defecto `subordinate`. Un asimilado o un trabajador por honorarios recibe sueldo e ISR sin subsidio, sin IMSS, sin SBC ni prestaciones de ley.                                                                                                                                                                                                                                                                                                                                                                                             |
| `minimum_wage_zone`                        | `general` \| `northern_border`                                                                                                | Por defecto `general` (Zona del Salario Mínimo General). `northern_border` es la Zona Libre de la Frontera Norte. Determina el salario mínimo contra el que se valida `daily_base_salary` y el que utiliza el cálculo de nómina.                                                                                                                                                                                                                                                                                                               |
| `salary_type`                              | `fixed` \| `mixed` \| `variable` \| null                                                                                      | Opcional. Tipo de salario del empleado: fijo, mixto o variable. Es informativo: no cambia el cálculo de la nómina.                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `imss_worker_type`                         | `permanent` \| `eventual_city` \| `eventual_construction` \| `eventual_rural` \| null                                         | Opcional. Tipo de trabajador IMSS: permanente, eventual de la ciudad, eventual de la construcción o eventual del campo. Obligatorio para dar de alta en nómina si `contributes_to_imss` es `true`; si es `false`, se guarda vacío.                                                                                                                                                                                                                                                                                                             |
| `imss_work_schedule`                       | `full` \| `one_day_week` \| `two_day_week` \| `three_day_week` \| `four_day_week` \| `five_day_week` \| `reduced_day` \| null | Opcional. Semana o jornada reducida: semana completa, semana reducida de 1 a 5 días o jornada reducida. Obligatorio para dar de alta en nómina si `contributes_to_imss` es `true`; si es `false`, se guarda vacío.                                                                                                                                                                                                                                                                                                                             |
| `is_unionized`                             | boolean                                                                                                                       | Por defecto `false`. Indica si el trabajador está sindicalizado.                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `receives_annual_isr_adjustment`           | boolean                                                                                                                       | Por defecto `true` para un `subordinate` y `false` para los demás. Un subordinado entra al ajuste anual de ISR solo si es `true`. Debe ser `false` cuando `worker_type` no es `subordinate` (sino `400`): un asimilado o un trabajador por honorarios nunca entra al ajuste.                                                                                                                                                                                                                                                                   |
| `opts_into_annual_isr_adjustment`          | boolean                                                                                                                       | **Obsoleto:** utiliza `receives_annual_isr_adjustment`. Un `true` se acepta como su equivalente; un `false` se ignora, porque antes no excluía a ningún subordinado. Si envías ambos, gana `receives_annual_isr_adjustment`. Las respuestas lo devuelven siempre en `false`: su significado era la solicitud de un asimilado o un trabajador por honorarios, que ya no existe. Antes un subordinado siempre entraba al ajuste; ahora `receives_annual_isr_adjustment` decide. Un error sobre este campo se reporta con el nombre que enviaste. |
| `is_included_in_payroll_calculations`      | boolean                                                                                                                       | Por defecto `true`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `daily_base_salary`                        | number                                                                                                                        | Sueldo diario base (> 0). Registra la primera fila del historial de sueldos. Cuenta para la preparación de nómina.                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `regimen_fiscal`                           | string                                                                                                                        | Clave SAT del régimen del trabajador (c\_TipoRegimen). Cuenta para la preparación de nómina. Debe corresponder al `worker_type`: `02` o `13` para `subordinate`, del `05` al `11` para `asimilado` y `honorarios` (sino `400`).                                                                                                                                                                                                                                                                                                                |
| `work_shift_type`                          | string                                                                                                                        | Clave SAT del tipo de jornada (c\_TipoJornada), por ejemplo `01` diurna. Va en el recibo timbrado y cuenta para la preparación de nómina.                                                                                                                                                                                                                                                                                                                                                                                                      |
| `benefit_scheme_number`                    | null                                                                                                                          | Ya no existe: las prestaciones del empleado vienen de su contrato (`contract_number`). Se acepta `null` y se ignora; cualquier otro valor responde `400`.                                                                                                                                                                                                                                                                                                                                                                                      |
| `payroll_calendar_number`                  | integer positivo                                                                                                              | Número del calendario de nómina; debe pertenecer a la `legal_entity_number` de la fila.                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `contract_number`                          | integer positivo                                                                                                              | Número del contrato; debe estar vinculado a la `legal_entity_number` de la fila.                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `work_schedule_number`                     | integer positivo                                                                                                              | Horario semanal fijo del empleado. Debe ser un horario **activo** de la organización. Excluyente con `work_schedule_bundle_number`.                                                                                                                                                                                                                                                                                                                                                                                                            |
| `work_schedule_bundle_number`              | integer positivo                                                                                                              | Rotación de horarios del empleado. Debe ser una rotación **activa** de la organización. Excluyente con `work_schedule_number`.                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `work_schedule_bundle_start_step`          | integer positivo                                                                                                              | Paso del ciclo en el que arranca el empleado. **Opcional**: si lo omites, se utiliza el primer paso de la rotación. Requiere `work_schedule_bundle_number` en el mismo cuerpo.                                                                                                                                                                                                                                                                                                                                                                 |
| `organizational_units`                     | integer\[]                                                                                                                    | Arreglo de números de unidad organizacional. Máximo una unidad por tipo.                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `activate`                                 | boolean                                                                                                                       | Omitido: da de alta (`active`) solo si el empleado está listo para nómina; de lo contrario queda `pending`. `true` exige que esté listo (sino `400` `ACTIVATION_INCOMPLETE`). `false` fuerza `pending`.                                                                                                                                                                                                                                                                                                                                        |
| `confirm_retro`                            | boolean                                                                                                                       | Autoriza que un alta con fecha de ingreso dentro de periodos **cerrados** se pague con ajustes retroactivos. Sin él, esa alta responde `409` `RETRO_CONFIRMATION_REQUIRED` y no se crea ningún empleado.                                                                                                                                                                                                                                                                                                                                       |

## Campos opcionales — valores de campos personalizados [#campos-opcionales--valores-de-campos-personalizados]

Los valores de campos personalizados se envían como **claves planas en la raíz del cuerpo del empleado**, no dentro de un objeto envoltorio. La clave es el `key` de la definición y el valor debe ser compatible con el `type` declarado:

| `type` de la definición | Valor JSON aceptado             |
| ----------------------- | ------------------------------- |
| `text`, `select`        | String no vacío.                |
| `number`                | Número finito.                  |
| `boolean`               | `true` o `false`.               |
| `date`                  | String en formato `YYYY-MM-DD`. |

Si una definición activa tiene `is_required_for_create: true`, su `key` debe enviarse en cada fila. Las definiciones opcionales pueden omitirse.

## 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 **plano** del empleado creado: datos personales + los de su empleo actual. El `status` es `active` solo si el empleado quedó listo para nómina; de lo contrario, `pending`.

```json
{
  "employee_number": 5,
  "internal_number": null,
  "first_name": "María",
  "middle_name": null,
  "paternal_last_name": "González",
  "maternal_last_name": null,
  "gender": null,
  "birth_date": null,
  "birth_country": null,
  "birth_state": null,
  "birth_state_code": null,
  "birth_municipality_code": null,
  "birth_city": null,
  "birth_place": null,
  "nationality": null,
  "phone_number": null,
  "secondary_phone_number": null,
  "rfc": "GOPM900101AB1",
  "curp": "GOPM900101MDFNRR07",
  "postal_code": null,
  "work_center_state_code": "CMX",
  "home_street": null,
  "home_exterior_number": null,
  "home_interior_number": null,
  "home_neighborhood": null,
  "home_municipality_code": null,
  "home_city": null,
  "home_state_code": null,
  "home_postal_code": null,
  "fiscal_address_same_as_home": false,
  "domicile_state_code": null,
  "fiscal_street": null,
  "fiscal_exterior_number": null,
  "fiscal_interior_number": null,
  "fiscal_neighborhood": null,
  "fiscal_municipality_code": null,
  "fiscal_city": null,
  "bank": null,
  "clabe": null,
  "account_number": null,
  "card_number": null,
  "notes": null,
  "legal_entity_number": 1,
  "status": "pending",
  "hire_date": "2026-01-15T00:00:00.000Z",
  "seniority_date": null,
  "termination_date": null,
  "job_position_code": null,
  "branch_code": null,
  "department_code": null,
  "cost_center_code": null,
  "employer_registration": null,
  "imss_number": null,
  "contributes_to_imss": false,
  "worker_type": "subordinate",
  "minimum_wage_zone": "general",
  "imss_worker_type": null,
  "imss_work_schedule": null,
  "salary_type": null,
  "is_unionized": false,
  "receives_annual_isr_adjustment": true,
  "opts_into_annual_isr_adjustment": false,
  "is_included_in_payroll_calculations": true,
  "daily_base_salary": null,
  "regimen_fiscal": null,
  "work_shift_type": null,
  "payroll_calendar_number": null,
  "contract_number": null,
  "work_schedule_number": null,
  "work_schedule_bundle_number": null,
  "work_schedule_bundle_start_step": null,
  "organizational_units": [],
  "created_at": "2026-05-25T10:00:00.000Z",
  "updated_at": "2026-05-25T10: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": [
    { "employee_number": 6, "...": "..." },
    { "employee_number": 7, "...": "..." }
  ]
}
```

## Errores [#errores]

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

Lista plana de problemas para el único empleado:

```json
{
  "message": "Validation failed.",
  "errors": [
    {
      "field": "rfc",
      "code": "DUPLICATE_RFC",
      "message": "An employee with this 'rfc' already exists in this organization."
    }
  ]
}
```

Para fallas de validación de esquema (campo faltante, tipo incorrecto), `errors` es un objeto indexado por campo:

```json
{
  "message": "Validation failed.",
  "errors": {
    "rfc": ["Ingresa el RFC."],
    "hire_date": ["Ingresa la fecha de ingreso."]
  }
}
```

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

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

```json
{
  "message": "Validation failed for 1 employee(s). No employees were created.",
  "summary": { "total": 2, "with_errors": 1 },
  "errors": [
    {
      "index": 0,
      "employee": { "first_name": "María", "paternal_last_name": "González" },
      "issues": [
        {
          "field": "legal_entity_number",
          "code": "LEGAL_ENTITY_NOT_FOUND",
          "message": "No legal entity with number '99' in this organization."
        }
      ]
    }
  ]
}
```

* `index` — posición 0-based de la fila que falló dentro del arreglo enviado.
* `employee.first_name` / `employee.paternal_last_name` — 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`: alta en periodos cerrados, número interno duplicado o condición de carrera [#409-alta-en-periodos-cerrados-número-interno-duplicado-o-condición-de-carrera]

Si un empleado se da de alta con una fecha de ingreso dentro de periodos ya cerrados y no enviaste `confirm_retro: true`, la respuesta es `409` con `errors[].code` `RETRO_CONFIRMATION_REQUIRED` y `retro_periods`. En modo lote, el error llega en la fila correspondiente y ningún empleado es creado.

Si otro empleado de la organización ya tiene el `internal_number` que enviaste (sin distinguir mayúsculas), la respuesta es `409` con `errors[].code` `DUPLICATE_INTERNAL_NUMBER`. En modo lote, dos filas con el mismo número también lo producen, y ningún empleado es creado.

Otra solicitud concurrente reclamó un RFC o CURP 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 empleado 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 esquema (formato, longitud, tipo).                                                                                                                                                                                              |
| `DUPLICATE_RFC`                      | El RFC ya existe en otro empleado de la organización.                                                                                                                                                                                                           |
| `DUPLICATE_CURP`                     | El CURP ya existe en otro empleado de la organización.                                                                                                                                                                                                          |
| `DUPLICATE_RFC_IN_BATCH`             | El mismo RFC aparece en más de una fila del lote.                                                                                                                                                                                                               |
| `DUPLICATE_CURP_IN_BATCH`            | El mismo CURP aparece en más de una fila del lote.                                                                                                                                                                                                              |
| `DUPLICATE_INTERNAL_NUMBER`          | El número interno ya lo tiene otro empleado de la organización (o se repite en el lote). Llega con estatus `409`.                                                                                                                                               |
| `LEGAL_ENTITY_NOT_FOUND`             | `legal_entity_number` no coincide con ninguna razón social de la organización.                                                                                                                                                                                  |
| `BELOW_MINIMUM_WAGE`                 | `daily_base_salary` es menor al salario mínimo diario vigente de la `minimum_wage_zone` del empleado. El mínimo se toma del catálogo `salario_minimo` de la organización y respeta el override de la razón social, así que puede variar entre razones sociales. |
| `JOB_POSITION_NOT_FOUND`             | `job_position_code` no coincide con un puesto activo.                                                                                                                                                                                                           |
| `BRANCH_NOT_FOUND`                   | `branch_code` no coincide con una sucursal activa.                                                                                                                                                                                                              |
| `DEPARTMENT_NOT_FOUND`               | `department_code` no coincide con un departamento activo.                                                                                                                                                                                                       |
| `COST_CENTER_NOT_FOUND`              | `cost_center_code` no coincide con un centro de costos activo.                                                                                                                                                                                                  |
| `EMPLOYER_REGISTRATION_NOT_FOUND`    | `employer_registration` no coincide con un registro patronal de la razón social de la fila.                                                                                                                                                                     |
| `PAYROLL_CALENDAR_NOT_FOUND`         | `payroll_calendar_number` no coincide con un calendario de nómina de la razón social de la fila.                                                                                                                                                                |
| `CONTRACT_NOT_FOUND`                 | `contract_number` no coincide con un contrato vinculado a la razón social de la fila.                                                                                                                                                                           |
| `WORK_SCHEDULE_NOT_FOUND`            | `work_schedule_number` no coincide con un horario activo de esta organización.                                                                                                                                                                                  |
| `WORK_SCHEDULE_BUNDLE_NOT_FOUND`     | `work_schedule_bundle_number` no coincide con una rotación activa de esta organización.                                                                                                                                                                         |
| `INVALID_WORK_SCHEDULE_BUNDLE_STEP`  | `work_schedule_bundle_start_step` nombra un paso que la rotación no tiene, o la rotación no tiene pasos.                                                                                                                                                        |
| `ORGANIZATIONAL_UNIT_NOT_FOUND`      | Un número de `organizational_units` no coincide con una unidad organizacional activa.                                                                                                                                                                           |
| `ORGANIZATIONAL_UNIT_DUPLICATE_TYPE` | Se enviaron dos unidades del mismo tipo en `organizational_units`.                                                                                                                                                                                              |
| `CUSTOM_FIELD_NOT_FOUND`             | Una clave plana del cuerpo no corresponde a un campo nativo ni a una definición de campo personalizado activa.                                                                                                                                                  |
| `CUSTOM_FIELD_INVALID_TYPE`          | El valor enviado para un campo personalizado no coincide con el `type` declarado de la definición.                                                                                                                                                              |
| `CUSTOM_FIELD_REQUIRED`              | Una definición activa con `is_required_for_create: true` no fue enviada para esa fila.                                                                                                                                                                          |
| `INVALID_HOME_MUNICIPALITY`          | `home_municipality_code` no pertenece a `home_state_code`, o se envió sin estado.                                                                                                                                                                               |
| `INVALID_FISCAL_MUNICIPALITY`        | `fiscal_municipality_code` no pertenece a `domicile_state_code`, o se envió sin estado. No se valida si `fiscal_address_same_as_home` es `true`.                                                                                                                |
| `INVALID_BIRTH_MUNICIPALITY`         | `birth_municipality_code` no pertenece a `birth_state_code`, o se envió sin estado.                                                                                                                                                                             |
| `INVALID_NATIONALITY`                | `nationality` no está en el catálogo de nacionalidades.                                                                                                                                                                                                         |
| `ACTIVATION_INCOMPLETE`              | `activate: true` en un empleado que no está listo para nómina; el mensaje enumera los datos faltantes. Llega con estatus `400`.                                                                                                                                 |
| `RETRO_CONFIRMATION_REQUIRED`        | El alta cae en periodos de nómina ya cerrados. Reenvía con `confirm_retro: true`. Llega con estatus `409`.                                                                                                                                                      |
| `CONCURRENT_MODIFICATION`            | Señal de reintento por condición de carrera (respuesta `409`).                                                                                                                                                                                                  |