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
endGraphQL 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:
| Category | Limit | Window |
|---|---|---|
| Authentication | 10 requests | 1 minute |
| Read operations | 1,000 requests | 1 minute |
| Write operations | 200 requests | 1 minute |
| BACEN message submission | 100 requests | 1 minute |
| Extracts | 20 requests | 1 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 histogramhttp_requests_total- Request counter by method, path, and statusgateway_upstream_duration_seconds- Upstream service latencygateway_rate_limit_exceeded_total- Rate limit violation counter