Files
nala 1106509116
tests / ci (push) Canceled after 0s
vrsao 2
2026-10-08 14:02:01 +02:00

1113 lines
47 KiB
YAML

openapi: 3.1.0
info:
title: InvestMoz API
version: 1.0.0
summary: Contrato consolidado da API do InvestMoz
description: |
Contrato consolidado para catálogos, oportunidades, manifestações de interesse,
simulações, legislação, jobs, relatórios e administração. Valores de taxas,
reduções e parâmetros de simulação são fornecidos pelo utilizador; não são
taxas oficiais nem decisões de elegibilidade.
contact:
name: Equipa InvestMoz
license:
name: MIT
identifier: MIT
servers:
- url: /
description: Mesmo host da aplicação
security:
- sessionCookie: []
tags:
- name: Catálogos
description: Referências versionadas, estáveis e localizadas em pt-MZ.
- name: Oportunidades
description: Consulta pública de oportunidades de investimento.
- name: Manifestações
description: Submissão de interesse em oportunidades.
- name: Simulações
description: Execuções indicativas com snapshots e controlo de concorrência.
- name: Jobs
description: Estado dos trabalhos assíncronos associados a uma simulação.
- name: Relatórios
description: Leitura de snapshots imutáveis de relatórios.
- name: Legislação
description: Fontes legais publicadas e versionadas.
- name: Administração
description: Operações administrativas protegidas por sessão e autorização.
paths:
/api/v1/catalogs/{catalog}:
get:
tags: [Catálogos]
operationId: listReferenceCatalog
summary: Consultar catálogo versionado
security: []
parameters:
- $ref: '#/components/parameters/CatalogName'
- $ref: '#/components/parameters/Version'
- $ref: '#/components/parameters/CatalogType'
- $ref: '#/components/parameters/ParentId'
- $ref: '#/components/parameters/JurisdictionId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
- $ref: '#/components/parameters/Search'
- $ref: '#/components/parameters/CorrelationId'
responses:
'200':
description: Página do catálogo na versão solicitada
headers:
ETag: { $ref: '#/components/headers/ETag' }
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema: { $ref: '#/components/schemas/CatalogPage' }
'404': { $ref: '#/components/responses/NotFound' }
'422': { $ref: '#/components/responses/ValidationError' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/questionnaires/{code}:
get:
tags: [Simulações]
operationId: getPublishedQuestionnaire
summary: Consultar questionário publicado e versão imutável
security: []
parameters:
- $ref: '#/components/parameters/QuestionnaireCode'
- $ref: '#/components/parameters/CorrelationId'
responses:
'200':
description: Questionário publicado em pt-MZ
headers:
ETag: { $ref: '#/components/headers/ETag' }
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema:
{
$ref: '#/components/schemas/QuestionnaireResponse',
}
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/simulations:
post:
tags: [Simulações]
operationId: createSimulation
summary: Criar simulação rastreável
description: Requer Idempotency-Key. Acesso anónimo requer token opaco gerado pelo cliente.
x-implementation-status: implemented
security:
- sessionCookie: []
- {}
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
- $ref: '#/components/parameters/SimulationToken'
- $ref: '#/components/parameters/CorrelationId'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SimulationInput' }
examples:
BoundaryValues:
summary: Exemplo técnico nos limites mínimos
description: Valores mínimos para demonstrar a forma do payload; não são valores fiscais recomendados.
value: { base: 0, rate: 0, reduction: 0 }
responses:
'202':
description: Simulação aceite para processamento
headers:
ETag: { $ref: '#/components/headers/ETag' }
Location: { $ref: '#/components/headers/Location' }
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema:
{
$ref: '#/components/schemas/SimulationAccepted',
}
'200':
description: Repetição idempotente da resposta original
headers:
ETag: { $ref: '#/components/headers/ETag' }
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema:
{
$ref: '#/components/schemas/SimulationAccepted',
}
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/ValidationError' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/simulations/{id}:
get:
tags: [Simulações]
operationId: getSimulation
summary: Consultar simulação, cenários e estado de execução
x-implementation-status: implemented
security:
- sessionCookie: []
- {}
parameters:
- $ref: '#/components/parameters/SimulationId'
- $ref: '#/components/parameters/SimulationToken'
- $ref: '#/components/parameters/CorrelationId'
responses:
'200':
description: Simulação dentro do âmbito autorizado
headers:
ETag: { $ref: '#/components/headers/ETag' }
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema:
{
$ref: '#/components/schemas/SimulationResponse',
}
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/simulations/{id}/scenarios/{scenarioId}:
patch:
tags: [Simulações]
operationId: updateSimulationScenario
summary: Actualizar cenário com controlo optimista de concorrência
x-implementation-status: implemented
security:
- sessionCookie: []
- {}
parameters:
- $ref: '#/components/parameters/SimulationId'
- $ref: '#/components/parameters/ScenarioId'
- $ref: '#/components/parameters/IfMatch'
- $ref: '#/components/parameters/SimulationToken'
- $ref: '#/components/parameters/CorrelationId'
requestBody:
required: true
content:
application/json:
schema:
{ $ref: '#/components/schemas/UpdateScenarioInput' }
responses:
'202':
description: Alteração aceite e reexecução colocada em fila
headers:
ETag: { $ref: '#/components/headers/ETag' }
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema: { $ref: '#/components/schemas/Scenario' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'412': { $ref: '#/components/responses/PreconditionFailed' }
'422': { $ref: '#/components/responses/ValidationError' }
'428': { $ref: '#/components/responses/PreconditionRequired' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/simulations/{id}/jobs:
get:
tags: [Jobs]
operationId: listSimulationJobs
summary: Consultar jobs de execução e geração de relatórios
description: Contrato reservado para consulta dos jobs associados à simulação.
x-implementation-status: contract-only
security:
- sessionCookie: []
- {}
parameters:
- $ref: '#/components/parameters/SimulationId'
- $ref: '#/components/parameters/SimulationToken'
- $ref: '#/components/parameters/CorrelationId'
responses:
'200':
description: Jobs visíveis no âmbito autorizado
headers:
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema:
{ $ref: '#/components/schemas/JobCollection' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/simulations/{id}/reports/{reportId}:
get:
tags: [Relatórios]
operationId: getSimulationReport
summary: Obter snapshot imutável de relatório
x-implementation-status: implemented
security:
- sessionCookie: []
- {}
parameters:
- $ref: '#/components/parameters/SimulationId'
- $ref: '#/components/parameters/ReportId'
- $ref: '#/components/parameters/SimulationToken'
- $ref: '#/components/parameters/CorrelationId'
responses:
'200':
description: Snapshot e hash do relatório
headers:
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema:
{ $ref: '#/components/schemas/ReportResponse' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/legislation/sources:
get:
tags: [Legislação]
operationId: listLegislationSources
summary: Consultar fontes legais publicadas e versionadas
description: Contrato reservado para catálogo público de fontes; administração usa a API v2 existente.
x-implementation-status: contract-only
security: []
parameters:
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
- $ref: '#/components/parameters/Search'
- $ref: '#/components/parameters/CorrelationId'
responses:
'200':
description: Fontes legais publicadas
headers:
ETag: { $ref: '#/components/headers/ETag' }
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema:
{ $ref: '#/components/schemas/LegislationPage' }
'404': { $ref: '#/components/responses/NotFound' }
'422': { $ref: '#/components/responses/ValidationError' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v2/investment/admin/legal-sources:
get:
tags: [Administração, Legislação]
operationId: adminListLegalSources
summary: Listar fontes legais para administração
x-implementation-status: implemented
security: [{ sessionCookie: [] }]
parameters:
- $ref: '#/components/parameters/CorrelationId'
responses:
'200':
description: Lista de fontes legais
headers:
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema:
{
$ref: '#/components/schemas/AdminLegalSourcePage',
}
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
post:
tags: [Administração, Legislação]
operationId: adminCreateLegalSource
summary: Registar fonte legal para validação
x-implementation-status: implemented
security: [{ sessionCookie: [] }]
parameters:
- $ref: '#/components/parameters/CorrelationId'
requestBody:
required: true
content:
application/json:
schema:
{ $ref: '#/components/schemas/LegalSourceInput' }
responses:
'201':
description: Fonte legal registada
headers:
Location: { $ref: '#/components/headers/Location' }
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema: { $ref: '#/components/schemas/LegalSource' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/ValidationError' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v2/investment/admin/legal-sources/{id}/{action}:
post:
tags: [Administração, Legislação]
operationId: adminTransitionLegalSource
summary: Validar ou revogar uma fonte legal
x-implementation-status: implemented
security: [{ sessionCookie: [] }]
parameters:
- $ref: '#/components/parameters/SourceId'
- name: action
in: path
required: true
schema: { type: string, enum: [validate, revoke] }
- $ref: '#/components/parameters/CorrelationId'
requestBody:
required: true
content:
application/json:
schema:
{
$ref: '#/components/schemas/LegalSourceTransitionInput',
}
responses:
'200':
description: Estado actualizado
headers:
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema: { $ref: '#/components/schemas/LegalSource' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/interest-requests:
post:
tags: [Manifestações]
operationId: submitInterestRequest
summary: Submeter manifestação de interesse
x-implementation-status: implemented
security: []
parameters:
- $ref: '#/components/parameters/IdempotencyKeyOptional'
- $ref: '#/components/parameters/CorrelationId'
requestBody:
required: true
content:
application/json:
schema:
{
$ref: '#/components/schemas/InterestRequestInput',
}
responses:
'201':
description: Manifestação submetida
headers:
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema:
{
$ref: '#/components/schemas/InterestRequestResponse',
}
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'409': { $ref: '#/components/responses/Conflict' }
'422': { $ref: '#/components/responses/ValidationError' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/opportunities/{slug}:
get:
tags: [Oportunidades]
operationId: getOpportunity
summary: Consultar oportunidade publicada
x-implementation-status: implemented
security: []
parameters:
- name: slug
in: path
required: true
schema: { type: string, minLength: 1, maxLength: 180 }
- $ref: '#/components/parameters/CorrelationId'
responses:
'200':
description: Oportunidade publicada
headers:
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema:
{
$ref: '#/components/schemas/OpportunityResponse',
}
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/ServerError' }
components:
securitySchemes:
sessionCookie:
type: apiKey
in: cookie
name: laravel-session
description: Sessão Laravel; o nome pode ser substituído por SESSION_COOKIE. Rotas públicas e simulações anónimas substituem explicitamente este requisito.
parameters:
CatalogName:
name: catalog
in: path
required: true
schema:
{
type: string,
enum: [authorities, jurisdictions, economic-activities],
}
Version:
name: version
in: query
required: false
description: Versão estável publicada do catálogo
schema: { type: integer, minimum: 1 }
CatalogType:
name: type
in: query
required: false
description: Obrigatório para jurisdictions.
schema:
{
type: string,
enum: [country, province, district, admin_post, locality],
}
ParentId:
name: parent_id
in: query
schema: { type: string, format: uuid }
JurisdictionId:
name: jurisdiction_id
in: query
schema: { type: string, format: uuid }
Page:
name: page
in: query
schema: { type: integer, minimum: 1, default: 1 }
PerPage:
name: per_page
in: query
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
Search:
name: q
in: query
schema: { type: string, maxLength: 100 }
QuestionnaireCode:
name: code
in: path
required: true
schema: { type: string, pattern: '^[a-z0-9][a-z0-9-]{0,79}$' }
SimulationId:
name: id
in: path
required: true
schema: { type: string, format: uuid }
ScenarioId:
name: scenarioId
in: path
required: true
schema: { type: string, format: uuid }
ReportId:
name: reportId
in: path
required: true
schema: { type: string, format: uuid }
SourceId:
name: id
in: path
required: true
schema: { type: string, format: uuid }
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
description: Repetições com a mesma chave e payload devolvem a resposta original; payload diferente produz conflito.
schema: { type: string, minLength: 16, maxLength: 128 }
IdempotencyKeyOptional:
name: Idempotency-Key
in: header
required: false
description: Se fornecida, deve ser UUID; uma chave repetida com outro payload produz conflito.
schema: { type: string, format: uuid }
SimulationToken:
name: X-Simulation-Token
in: header
required: false
description: Obrigatório para acesso anónimo; token opaco do cliente, guardado apenas como hash.
schema: { type: string, minLength: 32, maxLength: 256 }
IfMatch:
name: If-Match
in: header
required: true
description: ETag forte da representação lida previamente.
schema: { type: string, minLength: 1, maxLength: 128 }
CorrelationId:
name: X-Correlation-ID
in: header
required: false
description: UUID opcional propagado pela aplicação; quando ausente, a aplicação cria um identificador.
schema: { type: string, format: uuid }
headers:
ETag:
description: Validador da representação; usado com If-Match em alterações concorrentes.
schema: { type: string }
Location:
description: URI relativa do recurso criado ou aceite.
schema: { type: string, format: uri-reference }
RetryAfter:
description: Segundos até à próxima tentativa.
schema: { type: integer, minimum: 0 }
CorrelationId:
description: Identificador de correlação da operação.
schema: { type: string, format: uuid }
responses:
Unauthorized:
description: Autenticação necessária ou sessão inválida
headers:
{
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' },
}
content:
{
application/json:
{ schema: { $ref: '#/components/schemas/Problem' } },
}
Forbidden:
description: Actor autenticado sem autorização para a operação
headers:
{
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' },
}
content:
{
application/json:
{ schema: { $ref: '#/components/schemas/Problem' } },
}
NotFound:
description: Recurso inexistente ou fora do âmbito visível
headers:
{
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' },
}
content:
{
application/json:
{ schema: { $ref: '#/components/schemas/Problem' } },
}
Conflict:
description: Conflito de estado, versão ou chave idempotente
headers:
{
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' },
}
content:
application/json:
schema: { $ref: '#/components/schemas/Problem' }
example:
{
message: A chave foi reutilizada com conteúdo diferente.,
code: idempotency_conflict,
}
PreconditionFailed:
description: If-Match não corresponde ao ETag actual
headers:
ETag: { $ref: '#/components/headers/ETag' }
X-Correlation-ID: { $ref: '#/components/headers/CorrelationId' }
content:
application/json:
schema: { $ref: '#/components/schemas/Problem' }
example:
{
message: A representação mudou; volte a consultar o recurso.,
code: stale_etag,
}
ValidationError:
description: Dados inválidos
headers:
{
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' },
}
content:
{
application/json:
{
schema:
{
$ref: '#/components/schemas/ValidationProblem',
},
},
}
RateLimited:
description: Limite de pedidos excedido
headers:
Retry-After: { $ref: '#/components/headers/RetryAfter' }
X-Correlation-ID: { $ref: '#/components/headers/CorrelationId' }
content:
{
application/json:
{ schema: { $ref: '#/components/schemas/Problem' } },
}
ServerError:
description: Erro interno; resposta não contém detalhes sensíveis
headers:
{
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' },
}
content:
{
application/json:
{ schema: { $ref: '#/components/schemas/Problem' } },
}
PreconditionRequired:
description: Header obrigatório em falta, como If-Match ou Idempotency-Key
headers:
{
X-Correlation-ID:
{ $ref: '#/components/headers/CorrelationId' },
}
content:
{
application/json:
{ schema: { $ref: '#/components/schemas/Problem' } },
}
schemas:
Problem:
type: object
required: [message]
properties:
message: { type: string }
code: { type: string }
correlation_id: { type: string, format: uuid }
additionalProperties: true
ValidationProblem:
allOf:
- $ref: '#/components/schemas/Problem'
- type: object
properties:
errors:
type: object
additionalProperties:
type: array
items: { type: string }
CatalogItem:
type: object
required: [id, value, code, name, label, locale, version_no]
properties:
id: { type: string, format: uuid }
value: { type: string }
code: { type: string }
name:
{
type: string,
description: Rótulo apresentado em português de Moçambique.,
}
label: { type: string }
locale: { type: string, const: pt-MZ }
parent_id: { type: [string, 'null'] }
type:
{
type: [string, 'null'],
enum:
[
country,
province,
district,
admin_post,
locality,
'null',
],
}
authority_type: { type: [string, 'null'] }
organization_id: { type: [string, 'null'], format: uuid }
jurisdiction_id: { type: [string, 'null'], format: uuid }
jurisdiction_name: { type: [string, 'null'] }
source_code: { type: [string, 'null'] }
sector_id: { type: [string, 'null'] }
version_no: { type: integer }
CatalogPage:
type: object
required: [data, meta]
properties:
data:
{
type: array,
items: { $ref: '#/components/schemas/CatalogItem' },
}
links:
type: object
properties:
next: { type: [string, 'null'], format: uri-reference }
previous:
{ type: [string, 'null'], format: uri-reference }
next_page_url: { type: [string, 'null'], format: uri-reference }
prev_page_url: { type: [string, 'null'], format: uri-reference }
current_page: { type: integer }
per_page: { type: integer }
total: { type: integer }
last_page: { type: integer }
meta:
allOf:
- $ref: '#/components/schemas/Pagination'
- type: object
properties:
catalog: { type: string }
version: { type: [integer, 'null'] }
locale: { type: string, const: pt-MZ }
source_version: { type: [string, 'null'] }
status:
{
type: string,
enum: [published, not_published],
}
Pagination:
type: object
required: [current_page, per_page, total]
properties:
current_page: { type: integer, minimum: 1 }
per_page: { type: integer, minimum: 1 }
total: { type: integer, minimum: 0 }
version: { type: string }
QuestionnaireResponse:
type: object
required: [data]
properties:
data:
type: object
required:
[id, code, version_no, locale, schema_snapshot, status]
properties:
id: { type: string, format: uuid }
code: { type: string }
version_no: { type: integer, minimum: 1 }
locale: { type: string, const: pt-MZ }
schema_snapshot:
{ type: object, additionalProperties: true }
status: { type: string, const: published }
valid_from: { type: [string, 'null'], format: date }
valid_to: { type: [string, 'null'], format: date }
SimulationInput:
type: object
required: [base, rate]
properties:
base:
{
type: number,
minimum: 0,
description: Valor de entrada sem moeda inferida.,
}
rate:
{
type: number,
minimum: 0,
maximum: 100,
description: Parâmetro fornecido pelo utilizador; não representa taxa oficial.,
}
reduction:
{ type: number, minimum: 0, maximum: 100, default: 0 }
organization_id: { type: [string, 'null'], format: uuid }
additionalProperties: false
UpdateScenarioInput:
type: object
required: [label, base, rate]
properties:
label: { type: string, minLength: 1, maxLength: 100 }
base: { type: number, minimum: 0 }
rate: { type: number, minimum: 0, maximum: 100 }
reduction:
{ type: number, minimum: 0, maximum: 100, default: 0 }
additionalProperties: false
SimulationAccepted:
type: object
required: [data, replayed]
properties:
data: { $ref: '#/components/schemas/Simulation' }
replayed: { type: boolean }
access_token:
{
type: string,
minLength: 32,
maxLength: 256,
description: Devolvido apenas para execução anónima.,
}
SimulationResponse:
type: object
required: [data]
properties:
data: { $ref: '#/components/schemas/Simulation' }
Simulation:
type: object
required: [id, status, version_no, created_at, updated_at]
properties:
id: { type: string, format: uuid }
questionnaire_version_id:
{ type: [string, 'null'], format: uuid }
organization_id: { type: [string, 'null'], format: uuid }
version_no: { type: integer, minimum: 1 }
status:
{
type: string,
enum: [queued, running, completed, failed, cancelled],
}
input_snapshot: { type: object, additionalProperties: true }
result_snapshot:
{ type: [object, 'null'], additionalProperties: true }
calculation_snapshot:
{ type: [object, 'null'], additionalProperties: true }
scenarios:
{
type: array,
items: { $ref: '#/components/schemas/Scenario' },
}
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
Scenario:
type: object
required: [id, code, label, version_no, parameters]
properties:
id: { type: string, format: uuid }
code: { type: string }
label: { type: string }
version_no: { type: integer, minimum: 1 }
parameters: { type: object, additionalProperties: true }
JobCollection:
type: object
required: [data]
properties:
data:
{
type: array,
items: { $ref: '#/components/schemas/SimulationJob' },
}
SimulationJob:
type: object
required:
[id, simulation_id, job_type, status, attempts, available_at]
properties:
id: { type: string, format: uuid }
simulation_id: { type: string, format: uuid }
job_type: { type: string, enum: [execute, report] }
status:
{
type: string,
enum: [pending, running, succeeded, failed],
}
attempts: { type: integer, minimum: 0, maximum: 3 }
available_at: { type: string, format: date-time }
started_at: { type: [string, 'null'], format: date-time }
finished_at: { type: [string, 'null'], format: date-time }
error_code: { type: [string, 'null'] }
ReportResponse:
type: object
required: [data]
properties:
data: { $ref: '#/components/schemas/SimulationReport' }
SimulationReport:
type: object
required: [id, simulation_id, version_no, status]
properties:
id: { type: string, format: uuid }
simulation_id: { type: string, format: uuid }
version_no: { type: integer, minimum: 1 }
status: { type: string, enum: [queued, ready, failed] }
report_snapshot:
{ type: [object, 'null'], additionalProperties: true }
report_sha256:
{ type: [string, 'null'], pattern: '^[0-9a-f]{64}$' }
LegislationPage:
type: object
required: [data, meta]
properties:
data:
{
type: array,
items: { $ref: '#/components/schemas/LegalSource' },
}
meta: { $ref: '#/components/schemas/Pagination' }
AdminLegalSourcePage:
type: object
required: [data]
properties:
data:
{
type: array,
items: { $ref: '#/components/schemas/LegalSource' },
}
current_page: { type: integer }
per_page: { type: integer }
total: { type: integer }
last_page: { type: integer }
first_page_url:
{ type: [string, 'null'], format: uri-reference }
last_page_url: { type: [string, 'null'], format: uri-reference }
next_page_url: { type: [string, 'null'], format: uri-reference }
prev_page_url: { type: [string, 'null'], format: uri-reference }
LegalSourceInput:
type: object
required:
[title, url, diploma, article, competent_entity, valid_from]
properties:
title: { type: string, minLength: 1, maxLength: 255 }
url:
{
type: string,
format: uri,
pattern: '^https://',
maxLength: 2000,
}
diploma: { type: string, maxLength: 255 }
article: { type: string, maxLength: 255 }
competent_entity: { type: string, maxLength: 255 }
valid_from: { type: string, format: date }
valid_until: { type: [string, 'null'], format: date }
additionalProperties: false
LegalSourceTransitionInput:
type: object
required: [version_no]
properties:
version_no: { type: integer, minimum: 1 }
additionalProperties: false
LegalSource:
type: object
properties:
id: { type: string, format: uuid }
title: { type: string }
url: { type: string, format: uri }
diploma: { type: string }
article: { type: string }
competent_entity: { type: string }
validation_status:
{ type: string, enum: [pending, validated, revoked] }
version_no: { type: integer }
valid_until: { type: [string, 'null'], format: date }
validator_id: { type: [integer, 'null'] }
validated_at: { type: [string, 'null'], format: date-time }
valid_from: { type: [string, 'null'], format: date }
InterestRequestInput:
type: object
required:
[
fullName,
email,
investorType,
country,
sectorInterest,
message,
privacyConsent,
]
properties:
fullName:
{
type: string,
minLength: 3,
maxLength: 150,
writeOnly: true,
}
email:
{
type: string,
format: email,
maxLength: 150,
writeOnly: true,
}
phone:
{ type: [string, 'null'], maxLength: 30, writeOnly: true }
investorType:
{
type: string,
enum:
[
individual,
empresa,
fundo,
entidade_publica,
outro,
],
}
country: { type: string, maxLength: 100 }
sectorInterest: { type: string, maxLength: 150 }
opportunityReference: { type: [string, 'null'], maxLength: 80 }
existingBusinessId: { type: [string, 'null'], format: uuid }
modality: { type: [string, 'null'], maxLength: 50 }
investmentRange: { type: [string, 'null'], maxLength: 80 }
message:
{
type: string,
minLength: 20,
maxLength: 2000,
writeOnly: true,
}
privacyConsent: { type: boolean, const: true }
shareWithProponent: { type: boolean, default: false }
additionalProperties: false
not:
allOf:
- required: [opportunityReference]
properties:
opportunityReference: { type: string, minLength: 1 }
- required: [existingBusinessId]
properties:
existingBusinessId: { type: string, format: uuid }
allOf:
- if:
required: [existingBusinessId]
properties:
existingBusinessId: { type: string }
then:
required: [modality]
properties:
modality:
{ type: string, minLength: 1, maxLength: 50 }
InterestRequestResponse:
type: object
required: [success, message, data]
properties:
success: { type: boolean, const: true }
message: { type: string }
data:
type: object
required: [reference, status]
properties:
reference: { type: string }
status: { type: string, const: received }
OpportunityResponse:
type: object
required: [success, data]
properties:
success: { type: boolean, const: true }
data:
type: object
required: [id, slug, title]
properties:
id: { type: [string, integer] }
slug: { type: string }
title: { type: string }
summary: { type: [string, 'null'] }
status: { type: string }