Download OpenAPI specification:
API de reconciliação de posições da From Investors para a Smartbrain, parceira
exclusiva desta integração. Todas as chamadas são server-to-server com a credencial
de parceiro emitida para a Smartbrain. Operações de escrita exigem o header
X-End-User-Id (usuário final da Smartbrain), usado para autoria dos runs e
rastreio de custo de IA.
Convenções: datas yyyy-MM-dd; camelCase; paginação page/pageSize.
Idempotência. Envie Idempotency-Key (até 64 caracteres, único por requisição)
nos POSTs de escrita. Dentro de 24 horas, repetir a mesma chave com o mesmo corpo
devolve a resposta original sem executar de novo, com o header
Idempotent-Replay: true. A mesma chave com corpo ou caminho diferente devolve 409.
Se a primeira chamada ainda estiver em processamento, a segunda também recebe 409:
repita em instantes. Resposta de erro não é guardada, então a mesma chave serve para
retentar a requisição que falhou.
Não se aplica a POST /auth/token (repetir precisa emitir token novo) nem ao import
de planilha, que é multipart e já é substitutivo por escritório, custodiante e
período.
A criação de escritório e de carteira é idempotente também por externalId,
independentemente do header.
Fora desta versão (documentado para planejamento, ainda não disponível):
push programático de posições por carteira (PUT .../custodian-positions e
.../consolidator-positions), consulta de consumo (GET /usage) e webhooks
(PUT /webhooks). Posições entram por importação de planilha, no endpoint por
escritório descrito em Positions.
| clientId required | string |
| clientSecret required | string |
{- "clientId": "string",
- "clientSecret": "string"
}{- "accessToken": "string",
- "tokenType": "Bearer",
- "expiresIn": 1800
}| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
| Idempotency-Key | string <= 64 characters Torna o POST seguro para retentativa por 24h. Repetição com o mesmo corpo devolve
a resposta original e o header |
| externalId required | string Id da organização no parceiro (único) |
| name required | string |
| taxId required | string CNPJ da empresa (14 dígitos, com ou sem máscara). Obrigatório: é a identidade fiscal do escritório, única na base. |
| aiConfidenceThreshold | number Confiança mínima p/ auto-confirmar sugestões N:M da IA (0-1, default 0.90) |
| isSandbox | boolean Default: false Escritório de sandbox (dados fictícios, mesma instância). Nesses escritórios a reconciliação pula as etapas de IA, então integrar não gera custo de modelo; o matching determinístico e as regras de grupo seguem funcionando. |
| aiMonthlyCostCapUsd | number Teto de custo de IA no mês (USD). Quando omitido, aplicamos um teto padrão conservador (proteção contra consumo muito acima do esperado). Ao atingir o teto, a reconciliação pula só as etapas de IA (não falha). |
{- "externalId": "string",
- "name": "string",
- "taxId": "string",
- "aiConfidenceThreshold": 0,
- "isSandbox": false,
- "aiMonthlyCostCapUsd": 0
}{- "officeId": 0,
- "externalId": "string",
- "name": "string",
- "code": "string",
- "isSandbox": true,
- "isActive": true,
- "aiMonthlyCostCapUsd": 0,
- "createdAt": "2019-08-24T14:15:22Z"
}| page | integer Default: 1 |
| pageSize | integer <= 200 Default: 50 |
{- "items": [
- {
- "officeId": 0,
- "externalId": "string",
- "name": "string",
- "code": "string",
- "isSandbox": true,
- "isActive": true,
- "aiMonthlyCostCapUsd": 0,
- "createdAt": "2019-08-24T14:15:22Z"
}
], - "pagination": {
- "page": 0,
- "pageSize": 0,
- "totalCount": 0,
- "totalPages": 0
}
}| officeId required | string |
| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
| Idempotency-Key | string <= 64 characters Torna o POST seguro para retentativa por 24h. Repetição com o mesmo corpo devolve
a resposta original e o header |
| externalId required | string Id da carteira no parceiro (único no office) |
| name required | string |
| consolidatorPortfolioCode | string Código da carteira no consolidador (para pull automático); omitir se usar push |
string E-mail de contato da carteira. Se omitido, geramos um placeholder no-reply. | |
| taxId | string CPF/CNPJ do investidor (opcional) |
Array of objects Contas de custódia (metadado; as posições entram pelo import de planilha) |
{- "externalId": "string",
- "name": "string",
- "consolidatorPortfolioCode": "string",
- "email": "string",
- "taxId": "string",
- "accounts": [
- {
- "custodian": "XP Investimentos",
- "accountNumber": "string",
- "contaSinacor": "string"
}
]
}{- "portfolioId": "string",
- "officeId": 0,
- "externalId": "string",
- "name": "string",
- "consolidatorPortfolioCode": "string",
- "accountsCount": 0,
- "createdAt": "2019-08-24T14:15:22Z"
}| officeId required | string |
| page | integer Default: 1 |
| pageSize | integer <= 200 Default: 50 |
{- "items": [
- {
- "portfolioId": "string",
- "officeId": 0,
- "externalId": "string",
- "name": "string",
- "consolidatorPortfolioCode": "string",
- "accountsCount": 0,
- "createdAt": "2019-08-24T14:15:22Z"
}
], - "pagination": {
- "page": 0,
- "pageSize": 0,
- "totalCount": 0,
- "totalPages": 0
}
}Fluxo principal de custódia: o usuário final envia a planilha da instituição, no modelo específico (XP, Genial, BTG) ou no modelo genérico, exatamente como já acontece hoje na plataforma. O backend parseia com o importador correspondente.
É por ESCRITÓRIO, não por carteira: a planilha da instituição cobre todas as contas do escritório. A reconciliação atribui cada linha à carteira certa pelas contas cadastradas no provisionamento.
Substitutivo por (escritório, custodiante, período): cada import troca a carga anterior, então reenviar o mesmo arquivo é seguro e não duplica posições.
O período é mensal (MM-AAAA) porque é assim que as posições de custódia são armazenadas e consultadas pela reconciliação.
| officeId required | string |
| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
| file required | string <binary> Planilha .xlsx no modelo indicado (até 25 MB) |
| model required | string Enum: "xp" "genial" "btg" "generic" Modelo da planilha; "generic" = layout genérico da plataforma |
| period required | string^(0[1-9]|1[0-2])-\d{4}$ Período de referência no formato MM-AAAA |
{- "accepted": 0,
- "replaced": 0,
- "custodian": "string",
- "period": "07-2026"
}| portfolioId required | string |
| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
| Idempotency-Key | string <= 64 characters Torna o POST seguro para retentativa por 24h. Repetição com o mesmo corpo devolve
a resposta original e o header |
| date required | string <date> |
| mode | string Default: "sync" Enum: "sync" "async" async → 202 + polling/webhook (Fase 3) |
{- "date": "2019-08-24",
- "mode": "sync"
}{- "runId": "string",
- "portfolioId": "string",
- "date": "2019-08-24",
- "status": "queued",
- "matchedCount": 0,
- "groupMatchCount": 0,
- "unmatchedConsolidatorCount": 0,
- "unmatchedCustodianCount": 0,
- "totalConsolidatorValue": 0,
- "totalCustodianValue": 0,
- "totalDifference": 0,
- "createdAt": "2019-08-24T14:15:22Z",
- "createdByEndUserId": "string",
- "pairs": [
- {
- "pairId": "string",
- "mappingId": "string",
- "matchOrigin": "saved-mapping",
- "confidence": 0,
- "justification": "string",
- "consolidatorPosition": {
- "code": "string",
- "name": "string",
- "description": "string",
- "assetClass": "Renda Fixa",
- "assetType": "string",
- "institution": "string",
- "quantity": 0,
- "grossValue": 0,
- "positionId": "string"
}, - "custodianPosition": {
- "ticker": "string",
- "isin": "string",
- "cnpj": "string",
- "cetipCode": "string",
- "description": "string",
- "type": "Fundo",
- "issuer": "string",
- "accountNumber": "string",
- "quantity": 0,
- "grossValue": 0,
- "positionId": "string",
- "custodian": "string"
}, - "valueDifference": 0
}
], - "groupMatches": [
- {
- "matchId": "string",
- "matchType": "Manual",
- "status": "Confirmed",
- "ruleId": "string",
- "consolidatorItems": [
- "string"
], - "custodianItems": [
- "string"
], - "consolidatorTotalValue": 0,
- "custodianTotalValue": 0,
- "consolidatorTotalQuantity": 0,
- "custodianTotalQuantity": 0,
- "difference": 0,
- "aiConfidence": 0,
- "aiReason": "string"
}
], - "pendingSuggestions": [
- {
- "matchId": "string",
- "matchType": "Manual",
- "status": "Confirmed",
- "ruleId": "string",
- "consolidatorItems": [
- "string"
], - "custodianItems": [
- "string"
], - "consolidatorTotalValue": 0,
- "custodianTotalValue": 0,
- "consolidatorTotalQuantity": 0,
- "custodianTotalQuantity": 0,
- "difference": 0,
- "aiConfidence": 0,
- "aiReason": "string"
}
], - "unmatchedConsolidator": [
- {
- "code": "string",
- "name": "string",
- "description": "string",
- "assetClass": "Renda Fixa",
- "assetType": "string",
- "institution": "string",
- "quantity": 0,
- "grossValue": 0,
- "positionId": "string"
}
], - "unmatchedCustodian": [
- {
- "ticker": "string",
- "isin": "string",
- "cnpj": "string",
- "cetipCode": "string",
- "description": "string",
- "type": "Fundo",
- "issuer": "string",
- "accountNumber": "string",
- "quantity": 0,
- "grossValue": 0,
- "positionId": "string",
- "custodian": "string"
}
]
}| portfolioId required | string |
| from | string <date> |
| to | string <date> |
| page | integer Default: 1 |
| pageSize | integer <= 200 Default: 50 |
{- "items": [
- {
- "runId": "string",
- "portfolioId": "string",
- "date": "2019-08-24",
- "status": "queued",
- "matchedCount": 0,
- "groupMatchCount": 0,
- "unmatchedConsolidatorCount": 0,
- "unmatchedCustodianCount": 0,
- "totalConsolidatorValue": 0,
- "totalCustodianValue": 0,
- "totalDifference": 0,
- "createdAt": "2019-08-24T14:15:22Z",
- "createdByEndUserId": "string"
}
], - "pagination": {
- "page": 0,
- "pageSize": 0,
- "totalCount": 0,
- "totalPages": 0
}
}{- "runId": "string",
- "portfolioId": "string",
- "date": "2019-08-24",
- "status": "queued",
- "matchedCount": 0,
- "groupMatchCount": 0,
- "unmatchedConsolidatorCount": 0,
- "unmatchedCustodianCount": 0,
- "totalConsolidatorValue": 0,
- "totalCustodianValue": 0,
- "totalDifference": 0,
- "createdAt": "2019-08-24T14:15:22Z",
- "createdByEndUserId": "string"
}Devolve o resumo e os grupos N:M (que são persistidos).
Atenção: pairs, unmatchedConsolidator e unmatchedCustodian vêm vazios
aqui. O detalhe linha a linha não é armazenado, então só está disponível na
resposta do POST que executa a reconciliação. Guarde esse payload se precisar
exibi-lo depois, ou execute a reconciliação novamente.
| runId required | string |
{- "runId": "string",
- "portfolioId": "string",
- "date": "2019-08-24",
- "status": "queued",
- "matchedCount": 0,
- "groupMatchCount": 0,
- "unmatchedConsolidatorCount": 0,
- "unmatchedCustodianCount": 0,
- "totalConsolidatorValue": 0,
- "totalCustodianValue": 0,
- "totalDifference": 0,
- "createdAt": "2019-08-24T14:15:22Z",
- "createdByEndUserId": "string",
- "pairs": [
- {
- "pairId": "string",
- "mappingId": "string",
- "matchOrigin": "saved-mapping",
- "confidence": 0,
- "justification": "string",
- "consolidatorPosition": {
- "code": "string",
- "name": "string",
- "description": "string",
- "assetClass": "Renda Fixa",
- "assetType": "string",
- "institution": "string",
- "quantity": 0,
- "grossValue": 0,
- "positionId": "string"
}, - "custodianPosition": {
- "ticker": "string",
- "isin": "string",
- "cnpj": "string",
- "cetipCode": "string",
- "description": "string",
- "type": "Fundo",
- "issuer": "string",
- "accountNumber": "string",
- "quantity": 0,
- "grossValue": 0,
- "positionId": "string",
- "custodian": "string"
}, - "valueDifference": 0
}
], - "groupMatches": [
- {
- "matchId": "string",
- "matchType": "Manual",
- "status": "Confirmed",
- "ruleId": "string",
- "consolidatorItems": [
- "string"
], - "custodianItems": [
- "string"
], - "consolidatorTotalValue": 0,
- "custodianTotalValue": 0,
- "consolidatorTotalQuantity": 0,
- "custodianTotalQuantity": 0,
- "difference": 0,
- "aiConfidence": 0,
- "aiReason": "string"
}
], - "pendingSuggestions": [
- {
- "matchId": "string",
- "matchType": "Manual",
- "status": "Confirmed",
- "ruleId": "string",
- "consolidatorItems": [
- "string"
], - "custodianItems": [
- "string"
], - "consolidatorTotalValue": 0,
- "custodianTotalValue": 0,
- "consolidatorTotalQuantity": 0,
- "custodianTotalQuantity": 0,
- "difference": 0,
- "aiConfidence": 0,
- "aiReason": "string"
}
], - "unmatchedConsolidator": [
- {
- "code": "string",
- "name": "string",
- "description": "string",
- "assetClass": "Renda Fixa",
- "assetType": "string",
- "institution": "string",
- "quantity": 0,
- "grossValue": 0,
- "positionId": "string"
}
], - "unmatchedCustodian": [
- {
- "ticker": "string",
- "isin": "string",
- "cnpj": "string",
- "cetipCode": "string",
- "description": "string",
- "type": "Fundo",
- "issuer": "string",
- "accountNumber": "string",
- "quantity": 0,
- "grossValue": 0,
- "positionId": "string",
- "custodian": "string"
}
]
}Mesmo layout de planilha usado na plataforma, incluindo a seção de grupos N:M.
Como o detalhe linha a linha não é armazenado, o arquivo é remontado recalculando a reconciliação daquela data. O download não cria um run novo no histórico, mas se as posições mudaram desde a execução original os números podem diferir.
| runId required | string |
{- "error": {
- "code": "validation_error",
- "message": "string",
- "details": [
- "string"
], - "traceId": "string"
}
}Os dois lados são os OBJETOS COMPLETOS devolvidos pela reconciliação (mesma forma de consolidatorPosition/custodianPosition na resposta do run), não apenas um id: o motor aprende o mapeamento a partir dos dados do ativo. Recomenda-se reenviar exatamente o objeto recebido na lista de não-pareados.
| portfolioId required | string |
| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
| Idempotency-Key | string <= 64 characters Torna o POST seguro para retentativa por 24h. Repetição com o mesmo corpo devolve
a resposta original e o header |
required | object (ConsolidatorPositionInput) |
required | object (CustodianPositionInput) |
| justification | string |
{- "consolidatorPosition": {
- "code": "string",
- "name": "string",
- "description": "string",
- "assetClass": "Renda Fixa",
- "assetType": "string",
- "institution": "string",
- "quantity": 0,
- "grossValue": 0
}, - "custodianPosition": {
- "ticker": "string",
- "isin": "string",
- "cnpj": "string",
- "cetipCode": "string",
- "description": "string",
- "type": "Fundo",
- "issuer": "string",
- "accountNumber": "string",
- "quantity": 0,
- "grossValue": 0
}, - "justification": "string"
}{- "mappingId": "string",
- "pair": {
- "pairId": "string",
- "mappingId": "string",
- "matchOrigin": "saved-mapping",
- "confidence": 0,
- "justification": "string",
- "consolidatorPosition": {
- "code": "string",
- "name": "string",
- "description": "string",
- "assetClass": "Renda Fixa",
- "assetType": "string",
- "institution": "string",
- "quantity": 0,
- "grossValue": 0,
- "positionId": "string"
}, - "custodianPosition": {
- "ticker": "string",
- "isin": "string",
- "cnpj": "string",
- "cetipCode": "string",
- "description": "string",
- "type": "Fundo",
- "issuer": "string",
- "accountNumber": "string",
- "quantity": 0,
- "grossValue": 0,
- "positionId": "string",
- "custodian": "string"
}, - "valueDifference": 0
}
}| mappingId required | string |
| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
{- "error": {
- "code": "validation_error",
- "message": "string",
- "details": [
- "string"
], - "traceId": "string"
}
}Assim como no match manual 1:1, os dois lados são os objetos completos das posições selecionadas (do resultado da reconciliação), não ids. Diferente da confirmação de sugestão de IA, o match manual de grupo SEMPRE gera uma regra reutilizável, na mesma convenção do 1:1 da plataforma. Não há opção de não salvar como regra.
| runId required | string |
| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
| Idempotency-Key | string <= 64 characters Torna o POST seguro para retentativa por 24h. Repetição com o mesmo corpo devolve
a resposta original e o header |
required | Array of objects (ConsolidatorPositionInput) non-empty |
required | Array of objects (CustodianPositionInput) non-empty |
| description | string |
{- "consolidatorPositions": [
- {
- "code": "string",
- "name": "string",
- "description": "string",
- "assetClass": "Renda Fixa",
- "assetType": "string",
- "institution": "string",
- "quantity": 0,
- "grossValue": 0
}
], - "custodianPositions": [
- {
- "ticker": "string",
- "isin": "string",
- "cnpj": "string",
- "cetipCode": "string",
- "description": "string",
- "type": "Fundo",
- "issuer": "string",
- "accountNumber": "string",
- "quantity": 0,
- "grossValue": 0
}
], - "description": "string"
}{- "matchId": "string",
- "matchType": "Manual",
- "status": "Confirmed",
- "ruleId": "string",
- "consolidatorItems": [
- "string"
], - "custodianItems": [
- "string"
], - "consolidatorTotalValue": 0,
- "custodianTotalValue": 0,
- "consolidatorTotalQuantity": 0,
- "custodianTotalQuantity": 0,
- "difference": 0,
- "aiConfidence": 0,
- "aiReason": "string"
}| runId required | string |
| matchId required | string |
| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
{- "error": {
- "code": "validation_error",
- "message": "string",
- "details": [
- "string"
], - "traceId": "string"
}
}| runId required | string |
| matchId required | string |
| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
| Idempotency-Key | string <= 64 characters Torna o POST seguro para retentativa por 24h. Repetição com o mesmo corpo devolve
a resposta original e o header |
| saveAsRule | boolean Default: true |
{- "saveAsRule": true
}{- "matchId": "string",
- "matchType": "Manual",
- "status": "Confirmed",
- "ruleId": "string",
- "consolidatorItems": [
- "string"
], - "custodianItems": [
- "string"
], - "consolidatorTotalValue": 0,
- "custodianTotalValue": 0,
- "consolidatorTotalQuantity": 0,
- "custodianTotalQuantity": 0,
- "difference": 0,
- "aiConfidence": 0,
- "aiReason": "string"
}| runId required | string |
| matchId required | string |
| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
| Idempotency-Key | string <= 64 characters Torna o POST seguro para retentativa por 24h. Repetição com o mesmo corpo devolve
a resposta original e o header |
| officeId required | string |
[- {
- "ruleId": "string",
- "ruleType": "OneToMany",
- "consolidatorSide": [
- "string"
], - "custodianSide": [
- "string"
], - "description": "string",
- "isActive": true,
- "createdAt": "2019-08-24T14:15:22Z"
}
]| ruleId required | string |
| X-End-User-Id required | string Id estável do usuário final no parceiro (autoria + custo de IA) |
| description | string |
| isActive | boolean |
{- "description": "string",
- "isActive": true
}