Skip to content

API Gateway

The API Gateway (api_gateway) is the single entry point for all external HTTP traffic into the FluxiQ SPB platform. It provides REST and GraphQL interfaces, request routing, rate limiting, and authentication enforcement.

Port: 4000

Responsibilities

  • Route incoming HTTP requests to the appropriate downstream microservice
  • Enforce JWT authentication on protected endpoints
  • Provide a unified GraphQL API via Absinthe
  • Apply rate limiting per client, tenant, and endpoint
  • Handle request/response transformation and content negotiation
  • Aggregate responses from multiple services when needed
  • Serve as the TLS termination point for external traffic

Configuration

elixir
# config/runtime.exs
config :api_gateway, ApiGateway.Endpoint,
  http: [port: 4000],
  url: [host: System.get_env("HOST", "localhost")],
  secret_key_base: System.fetch_env!("SECRET_KEY_BASE")

config :api_gateway, :rate_limit,
  window_ms: 60_000,
  max_requests: 1000,
  by: :client_id

config :api_gateway, :services,
  auth: System.get_env("AUTH_SERVICE_URL", "http://localhost:4001"),
  bacen: System.get_env("BACEN_GATEWAY_URL", "http://localhost:4002"),
  processor: System.get_env("MESSAGE_PROCESSOR_URL", "http://localhost:4003"),
  users: System.get_env("USER_MANAGEMENT_URL", "http://localhost:4004"),
  transactions: System.get_env("TRANSACTION_SERVICE_URL", "http://localhost:4005"),
  securities: System.get_env("SECURITIES_SERVICE_URL", "http://localhost:4006"),
  settlements: System.get_env("SETTLEMENT_SERVICE_URL", "http://localhost:4007"),
  forex: System.get_env("FOREX_SERVICE_URL", "http://localhost:4008"),
  cash: System.get_env("CASH_SERVICE_URL", "http://localhost:4009"),
  extracts: System.get_env("EXTRACT_SERVICE_URL", "http://localhost:4010")

REST API Routes

The gateway exposes a versioned REST API under /api/v1:

elixir
scope "/api/v1", ApiGateway do
  pipe_through [:api]

  # Public routes
  post "/auth/login", AuthController, :login
  post "/auth/refresh", AuthController, :refresh

  pipe_through [:authenticated]

  # Transaction routes
  get    "/transactions", TransactionController, :index
  post   "/transactions/str", TransactionController, :create_str
  post   "/transactions/ted", TransactionController, :create_ted
  post   "/transactions/doc", TransactionController, :create_doc
  get    "/transactions/:id", TransactionController, :show
  post   "/transactions/:id/cancel", TransactionController, :cancel

  # STR specific
  get  "/str/balance", STRController, :balance
  get  "/str/statement", STRController, :statement

  # Securities routes
  get    "/securities/positions", SecuritiesController, :positions
  post   "/securities/transfer", SecuritiesController, :transfer
  post   "/securities/pledge", SecuritiesController, :pledge

  # Settlement routes
  get  "/settlements/windows", SettlementController, :windows
  get  "/settlements/net-position", SettlementController, :net_position
  post "/settlements/batch", SettlementController, :submit_batch

  # Forex routes
  get  "/forex/ptax", ForexController, :ptax_rate
  post "/forex/contract", ForexController, :create_contract

  # Cash routes
  post "/cash/order", CashController, :create_order
  get  "/cash/balance", CashController, :balance

  # Extracts
  get  "/extracts", ExtractController, :index
  post "/extracts", ExtractController, :create
  get  "/extracts/:id/download", ExtractController, :download
end

GraphQL API

The gateway also exposes a GraphQL endpoint powered by Absinthe:

graphql
type Query {
  transaction(id: ID!): Transaction
  transactions(filter: TransactionFilter, page: Int, pageSize: Int): TransactionPage
  strBalance: STRBalance
  securitiesPositions: [SecurityPosition]
  settlementWindows: [SettlementWindow]
  ptaxRate(currency: String!, date: Date): PTAXRate
}

type Mutation {
  createTED(input: TEDInput!): TransactionResult
  createSTR(input: STRInput!): TransactionResult
  cancelTransaction(id: ID!, reason: String!): TransactionResult
  createForexContract(input: ForexInput!): ForexContractResult
}

type Subscription {
  transactionStatusChanged(id: ID!): Transaction
  settlementWindowOpened: SettlementWindow
}

Access the GraphQL playground at http://localhost:4000/graphql in development mode.

Rate Limiting

Rate limits are enforced per tenant and endpoint category:

CategoryLimitWindow
Authentication10 requests1 minute
Read operations1,000 requests1 minute
Write operations200 requests1 minute
BACEN message submission100 requests1 minute
Extracts20 requests1 minute

When a rate limit is exceeded, the gateway returns HTTP 429 with a Retry-After header.

Health Check

bash
# Liveness probe
curl http://localhost:4000/health/live
# Returns: {"status": "ok"}

# Readiness probe (checks downstream service connectivity)
curl http://localhost:4000/health/ready
# Returns: {"status": "ok", "services": {"auth": "up", "transactions": "up", ...}}

Metrics

The gateway exports Prometheus metrics at /metrics:

  • http_request_duration_seconds - Request latency histogram
  • http_requests_total - Request counter by method, path, and status
  • gateway_upstream_duration_seconds - Upstream service latency
  • gateway_rate_limit_exceeded_total - Rate limit violation counter

Plataforma de Integracao BACEN/SPB