865 lines
35 KiB
YAML
865 lines
35 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}
|