templateId). O sistema valida o snapshot armazenado no template (camadas 1, 2 e 3) contra os dados informados — typeSpecificFields contra baseTypeFields do template e customFields contra os campos customizados (ver ContractTemplates.md).clientId (com role = DEBTOR).clientId (com role = CREDITOR). Pode ser a própria empresa via Client espelho (ver Participantes.md, seção 1.1) ou outro Client.CLIENT_NOT_FOUND.CREDITOR informado ganham automaticamente o Client espelho da empresa (isCompany = true). O sistema registra essa atribuição automática como evento PARTICIPANT_ADDED no ContractHistory (ver Contratos.md, seção 2.3) com referência clara de que foi resultado da migração.| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| id | UUID | Sim | Identificador único. |
| companyId | UUID | Sim | Empresa. |
| portfolioId | UUID | Sim | Portfolio de destino. |
| source | Enum | Sim | API na v1. |
| importMode | Enum | Sim | CONTRACTS_AND_PAYMENTS, CONTRACTS_ONLY, PAYMENTS_ONLY. |
| status | Enum | Sim | Status do job. Ver seção 2.3. |
| totalRecords | Integer | Não | Total de registros submetidos. Após validação. |
| validRecords | Integer | Não | Registros válidos. Após validação. |
| invalidRecords | Integer | Não | Registros com erros. Após validação. |
| warningRecords | Integer | Não | Registros com alertas. Após validação. |
| importedContracts | Integer | Não | Contratos importados. Após conclusão. |
| importedPayments | Integer | Não | Pagamentos importados. Após conclusão. |
| submittedBy | UUID | Sim | Usuário que iniciou. |
| confirmedBy | UUID | Não | Usuário que confirmou. |
| confirmedAt | DateTime (ISO 8601 UTC) | Não | Data da confirmação. |
| createdAt | DateTime (ISO 8601 UTC) | Sim | Data de criação. |
| updatedAt | DateTime (ISO 8601 UTC) | Sim | Última atualização. |
| completedAt | DateTime (ISO 8601 UTC) | Não | Data de conclusão. |
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| id | UUID | Sim | Identificador único. |
| importJobId | UUID | Sim | Job ao qual pertence. |
| recordIndex | Integer | Não | Índice do registro no payload. null para erros gerais. |
| field | String | Não | Campo com problema. Notação: typeSpecificFields.campo ou customFields.key. |
| errorCode | String | Sim | Código do erro. Ver seção 2.4. |
| errorMessage | String | Sim | Descrição legível. |
| severity | Enum | Sim | ERROR ou WARNING. |
| rawValue | String | Não | Valor original. |
| createdAt | DateTime (ISO 8601 UTC) | Sim | Data de criação. |
PENDING_VALIDATION ──► VALIDATED ──► IMPORTING ──► COMPLETED
│ └──► COMPLETED_WITH_ERRORS
└──► VALIDATION_FAILED
VALIDATED ──► CANCELLED| Status | Descrição |
|---|---|
PENDING_VALIDATION | Validação assíncrona em andamento. |
VALIDATED | Ao menos um registro válido. Aguardando confirmação. |
VALIDATION_FAILED | Nenhum registro válido. |
IMPORTING | Importação em andamento. |
COMPLETED | Todos os registros válidos importados. |
COMPLETED_WITH_ERRORS | Registros válidos importados; com ERROR ignorados. |
CANCELLED | Cancelado após validação. |
| Código | Severity | Descrição |
|---|---|---|
MISSING_REQUIRED_FIELD | ERROR | Campo obrigatório ausente. |
INVALID_DATE_FORMAT | ERROR | Formato inválido. |
INVALID_DATE_RANGE | ERROR | endDate anterior a startDate. |
INVALID_AMOUNT | ERROR | Valor inválido ou negativo. |
INVALID_ENUM_VALUE | ERROR | Valor não pertence ao enum. |
TEMPLATE_NOT_FOUND | ERROR | Template não encontrado. |
TEMPLATE_INACTIVE | ERROR | Template inativo. |
SUB_PORTFOLIO_REQUIRED | ERROR | subPortfolioId ausente no contrato. Toda importação exige carteira de destino. |
SUB_PORTFOLIO_NOT_FOUND | ERROR | Carteira informada não existe no portfolio de destino. |
SUB_PORTFOLIO_INACTIVE | ERROR | Carteira informada está inativa. |
CONTRACT_CODE_DUPLICATE | ERROR | Código já existe no portfolio. |
CONTRACT_CODE_DUPLICATE_IN_PAYLOAD | ERROR | Código duplicado dentro do payload. |
MISSING_TYPE_DESCRIPTION | ERROR | type = OTHER sem descrição. |
INTEREST_RATE_NOT_ALLOWED | ERROR | Juros para tipo que não aceita. |
MISSING_TYPE_SPECIFIC_FIELD | ERROR | Campo obrigatório do tipo base ausente. |
INVALID_TYPE_SPECIFIC_FIELD | ERROR | Campo do tipo base inválido. |
MISSING_CUSTOM_FIELD | ERROR | Campo obrigatório do template ausente. |
INVALID_CUSTOM_FIELD_VALUE | ERROR | Campo customizado inválido. |
| Código | Severity | Descrição |
|---|---|---|
DEBTOR_REQUIRED | ERROR | Nenhum devedor informado. |
CREDITOR_REQUIRED | ERROR | Nenhum credor informado e empresa não pode ser usada como fallback (situação anômala — ver RN-IMP-CREDITOR-FALLBACK). |
CLIENT_NOT_FOUND | ERROR | Client não encontrado na plataforma. |
INVALID_PARTICIPANT_ROLE | ERROR | Role não reconhecido. |
PARTICIPATION_PERCENTAGE_EXCEEDS_100 | ERROR | Soma dos participationPercentage dos credores excede 100%. |
| Código | Severity | Descrição |
|---|---|---|
CONTRACT_NOT_FOUND | ERROR | Contrato não existe (modo PAYMENTS_ONLY). |
DUE_DATE_OUT_OF_CONTRACT_RANGE | ERROR | dueDate fora da vigência. |
PAYMENT_CODE_DUPLICATE_IN_PAYLOAD | ERROR | Código duplicado no mesmo contrato. |
INCOMPATIBLE_PAYMENT_TYPE | ERROR | Tipo não permitido para o contrato. |
| Código | Severity | Descrição |
|---|---|---|
TOTAL_AMOUNT_MISMATCH | WARNING | Soma dos pagamentos diverge do totalAmount. |
ERROR excluídos. Registros WARNING importados.VALIDATED podem ser cancelados. IMPORTING não.subPortfolioId referenciando uma carteira ativa do portfolio de destino. Contratos sem subPortfolioId geram erro SUB_PORTFOLIO_REQUIRED. Carteira informada inválida ou inativa gera SUB_PORTFOLIO_NOT_FOUND ou SUB_PORTFOLIO_INACTIVE.CLIENT_NOT_FOUND quando não encontrado.CREDITOR informado, o sistema atribui automaticamente o Client espelho da empresa (isCompany = true) como credor com participationPercentage = 100%. Um evento PARTICIPANT_ADDED é registrado no ContractHistory indicando a atribuição automática como resultado de migração. Caso o Client espelho da empresa não exista (situação anômala), o erro CREDITOR_REQUIRED é gerado.allowedPaymentTypes do snapshot do template.GET /imports/:id.| Status | Código | Descrição |
|---|---|---|
| 404 | IMPORT_JOB_NOT_FOUND | Job não encontrado. |
| 422 | EMPTY_PAYLOAD | Nenhum registro no payload. |
| 422 | PAYLOAD_TOO_LARGE | Excede 500 registros (RN-IMP-011). |
| 422 | INVALID_IMPORT_MODE | Modo inválido. |
| 422 | JOB_NOT_VALIDATED | Confirmação antes da validação. |
| 422 | JOB_NOT_CANCELLABLE | Job em andamento. |
| 422 | VALIDATION_FAILED_NO_VALID_RECORDS | Nenhum registro válido. |
/v2/companies/:companyId/portfolios/:portfolioId/importsportfolio_import:create{
"importMode": "CONTRACTS_AND_PAYMENTS",
"contracts": [
{
"templateId": "tpl-001",
"subPortfolioId": "subport-001",
"code": "CPR-2024-001",
"description": "CPR Física — Soja Safra 24/25",
"total": 450000.00,
"currency": "COMMODITY_LINKED",
"startDate": "2024-03-01",
"endDate": "2025-04-30",
"paymentPeriodicity": "HARVEST",
"periodicityDescription": "Liquidação na colheita.",
"finePercentage": 2.0,
"typeSpecificFields": {
"crop": "SOYBEAN",
"harvestSeason": "2024/2025",
"expectedQuantity": 7500,
"quantityUnit": "BAGS_60KG",
"deliveryLocation": "Armazém Cooperativa — Lucas do Rio Verde/MT",
"deliveryDeadline": "2025-04-15"
},
"customFields": {
"variedadeSoja": "TMG7062",
"areaCultivada": 500.0
},
"participants": [
{ "clientId": "client-company-mirror", "role": "CREDITOR", "isPrimary": true, "participationPercentage": 100.0 },
{ "clientId": "client-002", "role": "DEBTOR", "isPrimary": true },
{ "clientId": "client-004", "role": "GUARANTOR" }
],
"payments": [
{
"code": "CPR-001",
"nominalAmount": 450000.00,
"dueDate": "2025-04-15",
"status": "PENDING"
}
]
}
]
}{
"id": "job-001",
"companyId": "company-001",
"portfolioId": "portfolio-001",
"source": "API",
"importMode": "CONTRACTS_AND_PAYMENTS",
"status": "PENDING_VALIDATION",
"totalRecords": null,
"validRecords": null,
"invalidRecords": null,
"warningRecords": null,
"importedContracts": null,
"importedPayments": null,
"submittedBy": "user-001",
"confirmedBy": null,
"confirmedAt": null,
"createdAt": "2025-03-20T09:00:00.000+00:00",
"updatedAt": "2025-03-20T09:00:00.000+00:00",
"completedAt": null
}{
"importMode": "PAYMENTS_ONLY",
"payments": [
{
"contractId": "contract-001",
"code": "NF-004",
"type": "INVOICE",
"nominalAmount": 50000.00,
"dueDate": "2024-12-01",
"status": "PENDING"
}
]
}portfolio_import:read{
"id": "job-001",
"companyId": "company-001",
"portfolioId": "portfolio-001",
"source": "API",
"importMode": "CONTRACTS_AND_PAYMENTS",
"status": "VALIDATED",
"totalRecords": 10,
"validRecords": 8,
"invalidRecords": 1,
"warningRecords": 1,
"importedContracts": null,
"importedPayments": null,
"submittedBy": "user-001",
"confirmedBy": null,
"confirmedAt": null,
"createdAt": "2025-03-20T09:00:00.000+00:00",
"updatedAt": "2025-03-20T09:05:00.000+00:00",
"completedAt": null
}portfolio_import:read| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
severity | Enum | Não | Filtrar por ERROR ou WARNING. |
errorCode | String | Não | Filtrar por código de erro específico. |
offset | Integer | Não | Default: 0. |
limit | Integer | Não | Default: 50. Máximo: 100. |
{
"items": [
{
"id": "err-001",
"importJobId": "job-001",
"recordIndex": 3,
"field": "participants[0].clientId",
"errorCode": "CLIENT_NOT_FOUND",
"errorMessage": "O cliente 'client-999' não foi encontrado na plataforma. Cadastre o cliente pelo módulo de Clientes do AgRisk.",
"severity": "ERROR",
"rawValue": "client-999",
"createdAt": "2025-03-20T09:05:00.000+00:00"
},
{
"id": "err-002",
"importJobId": "job-001",
"recordIndex": 5,
"field": "totalAmount",
"errorCode": "TOTAL_AMOUNT_MISMATCH",
"errorMessage": "Soma dos pagamentos (R$ 440.000) diverge do totalAmount (R$ 450.000).",
"severity": "WARNING",
"rawValue": "450000.00",
"createdAt": "2025-03-20T09:05:00.000+00:00"
}
],
"nextPage": false
}portfolio_import:create{}{
"id": "job-001",
"status": "IMPORTING",
"confirmedBy": "user-001",
"confirmedAt": "2025-03-20T09:10:00.000+00:00",
"updatedAt": "2025-03-20T09:10:00.000+00:00"
}portfolio_import:create{}{
"id": "job-001",
"status": "CANCELLED",
"updatedAt": "2025-03-20T09:08:00.000+00:00"
}portfolio_import:read| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
status | Enum (multi) | Não | Filtrar por status do job. |
orderBy | Enum | Não | Ordenação: createdAt, completedAt. Default: createdAt. |
order | Enum | Não | asc ou desc. Default: desc. |
offset | Integer | Não | Default: 0. |
limit | Integer | Não | Default: 20. Máximo: 100. |
{
"items": [
{
"id": "job-001",
"source": "API",
"importMode": "CONTRACTS_AND_PAYMENTS",
"status": "COMPLETED_WITH_ERRORS",
"totalRecords": 10,
"validRecords": 8,
"invalidRecords": 1,
"warningRecords": 1,
"importedContracts": 8,
"importedPayments": 24,
"submittedBy": "user-001",
"confirmedBy": "user-001",
"confirmedAt": "2025-03-20T09:10:00.000+00:00",
"createdAt": "2025-03-20T09:00:00.000+00:00",
"updatedAt": "2025-03-20T09:12:00.000+00:00",
"completedAt": "2025-03-20T09:12:00.000+00:00"
}
],
"nextPage": false
}templateId, mapeamento de colunas via interface.