NominexDocs
Referencia de la APIContratos

Crear

Crea uno o más contratos.

Descripcion general

Este endpoint permite crear uno o varios contratos 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. Un contrato es propiedad de la organización y se comparte entre las razones sociales que indiques en legal_entity_numbers mediante un puente (relación M:N). El campo contract_type corresponde a un código SAT c_TipoContrato (p. ej. "01" para indeterminado) y concept_numbers lista los conceptos de nómina extralegales que el contrato adjunta. Una solicitud única exitosa devuelve 201 con el contrato creado; una solicitud por lote devuelve 201 con { summary, created[] }.

Un contrato nuevo empieza con las prestaciones mínimas de ley: aguinaldo de 15 días, prima vacacional de 25 % y vacaciones según la tabla de ley.

Nota sobre concept_numbers: la API todavía no documenta cómo listar los conceptos de nómina, así que concept_numbers debe usar números que ya conozcas, o puedes omitirlo (arreglo vacío).

Endpoint

POSThttps://app.integranom.com/api/v1/contracts

Solicitud unica


Envía un objeto único con al menos legal_entity_numbers, name y contract_type. El contrato se crea activo por defecto y queda compartido por todas las razones sociales indicadas. Puedes omitir concept_numbers para crearlo sin conceptos adjuntos (arreglo vacío).

{
  "legal_entity_numbers": [1, 2],
  "name": "Indeterminado tiempo completo",
  "contract_type": "01",
  "concept_numbers": [7]
}

Solicitud por lote (1–100 contratos)


Envía un arreglo de hasta 100 contratos en el mismo endpoint; el modo lote se activa al enviar un arreglo como cuerpo. El lote es atómico: si cualquier fila falla la validación, ningún contrato se crea y la respuesta lista los problemas por fila.

[
  { "legal_entity_numbers": [1], "name": "Indeterminado tiempo completo", "contract_type": "01" },
  { "legal_entity_numbers": [1, 2], "name": "Por obra determinada", "contract_type": "03" }
]

Reglas de los campos

CampoTipoRequeridoNotas
legal_entity_numbersarreglo de enteros positivosSíAl menos 1 elemento. Las razones sociales que comparten el contrato.
namestringSí3–80 caracteres, sin contar espacios al inicio o al final, que no se guardan. Único por organización.
contract_typestringSíCódigo SAT c_TipoContrato (p. ej. "01").
descriptionstringNo≤ 280 caracteres.
concept_numbersarreglo de enteros positivosNoPor defecto []. Conceptos extralegales a adjuntar.
concept_calculationsarreglo de objetosNoEl cálculo que el contrato fija para un concepto. Cada objeto lleva concept_number y calculation (captured, fixed_amount o formula). Con fixed_amount envía amount (monto por periodo, mayor a cero, hasta 999,999,999,999.99 y con hasta dos decimales); con formula envía formula (texto de hasta 2000 caracteres, validado contra el vocabulario de fórmulas). Un concepto que no listas conserva su propio cálculo. El concepto debe venir también en concept_numbers. Cada concepto aparece una sola vez.
concept_valuesarreglo de objetosNoFormato anterior de concept_calculations, que se sigue aceptando. Cada objeto lleva concept_number y amount (monto por periodo, mayor a cero; se redondea a dos decimales) o rate_of_salary (fracción del salario del periodo, mayor a cero y hasta 1), nunca ambos: un monto se guarda como cálculo fixed_amount y una fracción como la fórmula var.sueldo_diario * var.dias_pagados * <fracción>. No se envía junto con concept_calculations. Si un concepto se repite, cuenta el último.

Prestaciones

Todas son opcionales al crear: lo que omitas toma el valor de ley, y lo que envíes se valida con los mínimos de ley sobre el resultado. Sin ninguna prestación el contrato queda como el de ley (is_legal_default en true); con al menos una es personalizado (template_key en null). Las mismas claves sirven para editar.

CampoTipoNotas
year_end_bonus_tableobject[]Renglones { years_from, years_to, days } con days ≥ 15. Empiezan en years_from 0, sin huecos ni traslapes, y solo el último tiene years_to en null. No se puede enviar junto con year_end_bonus_days.
year_end_bonus_daysintegerObsoleto: utiliza year_end_bonus_table. Un mismo aguinaldo, ≥ 15. Al editar solo se acepta si la tabla tiene un solo renglón.
year_end_bonus_discounts_absencesbooleanoSi las faltas injustificadas, los permisos y las vacaciones sin goce y las incapacidades por enfermedad general se descuentan de los días trabajados del aguinaldo y del finiquito. Por omisión es true; al editar, si lo omites se conserva el valor guardado.
vacation_tableobject[]Misma forma que year_end_bonus_table, por años cumplidos. El renglón del primer año (years_from 0) debe tener days ≥ 12.
vacation_premium_ratenúmeroEntre 0.25 y 1.
vacation_premium_payment_mode"on_days_taken" | "on_anniversary" | "not_calculated"Cuándo se paga la prima vacacional en todo el contrato.
sunday_premium_ratenúmeroEntre 0.25 y 1.
food_voucher_enabledbooleanSi es true, son obligatorios food_voucher_delivery_method y exactamente uno de food_voucher_rate o food_voucher_monthly_amount (> 0).
food_voucher_ratenúmero | nullEntre 0 y 0.5.
food_voucher_monthly_amountnúmero | nullMonto fijo mensual de vales.
food_voucher_delivery_method"card" | "cash" | nullMétodo de entrega.
food_voucher_capped_at_imss_exempt_limitbooleanLimita los vales del mes al tope exento del IMSS.
food_voucher_grant_frequency"every_run" | "monthly"Con "every_run" cada nómina paga su parte del monto mensual; con "monthly" una sola nómina paga el mes completo.
food_voucher_weekly_paying_run"week_1" | "week_2" | "week_3" | "week_4" | "last_week" | nullSemana que paga los vales. Requerido con "monthly", igual que los tres siguientes; con "every_run" o con los vales inactivos se guardan como null.
food_voucher_semimonthly_paying_run"first_half" | "second_half" | nullQuincena que paga los vales.
food_voucher_biweekly_paying_run"period_1" | "period_2" | "last_period" | nullCatorcena que paga los vales.
food_voucher_decennial_paying_run"period_1" | "period_2" | "period_3" | nullDecena que paga los vales.
savings_fund_enabledbooleanSi es true, savings_fund_employee_rate (> 0) y savings_fund_employer_rate son obligatorios.
savings_fund_employee_ratenúmero | nullEntre 0 y 0.13.
savings_fund_employer_ratenúmero | nullIgual a la del trabajador.
savings_fund_withdrawal_frequency"once_a_year" | "twice_a_year" | "more_than_twice_a_year" | nullRequerida cuando el fondo está activo; null cuando está inactivo.

Coherencia de conceptos

Cada número enviado en concept_numbers debe corresponder a un concepto activo y extralegal de tu organización, sin importar las razones sociales del contrato. Los conceptos de ley se calculan a cada empleado y nunca se adjuntan a un contrato. Si un número no cumple estas condiciones, la fila se rechaza con CONCEPT_NOT_FOUND.

Forma de las respuestas

201 — solicitud única

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

{
  "contract_number": 4,
  "name": "Indeterminado tiempo completo",
  "contract_type": "01",
  "description": null,
  "is_active": true,
  "sort_order": 0,
  "legal_entity_numbers": [1, 2],
  "concept_numbers": [7],
  "created_at": "2026-01-01T00:00:00.000Z",
  "updated_at": "2026-01-01T00:00:00.000Z"
}

Cada contrato de la respuesta incluye además template_key, is_legal_default, concept_calculations, concept_values (los montos fijos y las fórmulas de fracción del salario, en el formato anterior) y todas las prestaciones, más year_end_bonus_discounts_absences y year_end_bonus_days, que es null cuando la tabla de aguinaldo cambia con la antigüedad.

201 — solicitud por lote

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

{
  "summary": { "total": 2, "created": 2 },
  "created": [
    { "contract_number": 4, "...": "..." },
    { "contract_number": 5, "...": "..." }
  ]
}

Errores

400 — validación fallida (solicitud única)

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

{
  "message": "Validation failed.",
  "errors": { "name": ["El nombre debe tener entre 3 y 80 caracteres."] }
}

400 — validación fallida (solicitud por lote)

Reporte por fila. Ningún contrato del lote fue creado.

{
  "message": "Validation failed for 1 contract(s). No contracts were created.",
  "summary": { "total": 2, "with_errors": 1 },
  "errors": [
    {
      "index": 0,
      "contract": { "name": "Indeterminado tiempo completo" },
      "issues": [
        {
          "field": "concept_numbers",
          "code": "CONCEPT_NOT_FOUND",
          "message": "No se encontró un concepto extralegal activo con el número '7' en la organización."
        }
      ]
    }
  ]
}
  • index — posición 0-based de la fila que falló dentro del arreglo enviado.
  • contract.name — extraído 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 — nombre duplicado

Se devuelve cuando el name ya existe en la organización:

{
  "message": "A contract with this 'name' already exists in this organization."
}

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:

CodigoSignificado
INVALID_INPUTFalla genérica de validación de campos (formato, longitud, tipo).
LEGAL_ENTITY_NOT_FOUNDUn legal_entity_number no existe en esta organización.
CONCEPT_NOT_FOUNDUn concept_number no corresponde a un concepto extralegal activo.
CONCEPT_CALCULATION_NOT_ALLOWEDUn elemento de concept_calculations apunta a un concepto que no viene en concept_numbers, o a uno que calcula la plataforma o un crédito.
CONCEPT_VALUE_NOT_ALLOWEDUn elemento de concept_values apunta a un concepto que no viene en concept_numbers.
INVALID_BENEFITSLas prestaciones combinadas no cumplen sus reglas: vacaciones del primer año ≥ 12 días, la tabla completa sin huecos, y la coherencia de vales de despensa y fondo de ahorro. Un valor fuera de rango en un solo campo responde con errors por campo, sin este código.
Abrir Nominex