openapi: 3.1.0 info: title: SupplyChainService API version: 1.0.0 paths: /api/supply-chain/v1/get-shipping-rates: get: tags: - SupplyChainService summary: GetShippingRates operationId: GetShippingRates responses: "200": description: Successful response content: application/json: schema: $ref: '#/components/schemas/GetShippingRatesResponse' "400": description: Validation error content: application/json: schema: $ref: '#/components/schemas/ValidationError' default: description: Error response content: application/json: schema: $ref: '#/components/schemas/Error' /api/supply-chain/v1/get-chokepoint-status: get: tags: - SupplyChainService summary: GetChokepointStatus operationId: GetChokepointStatus responses: "200": description: Successful response content: application/json: schema: $ref: '#/components/schemas/GetChokepointStatusResponse' "400": description: Validation error content: application/json: schema: $ref: '#/components/schemas/ValidationError' default: description: Error response content: application/json: schema: $ref: '#/components/schemas/Error' /api/supply-chain/v1/get-critical-minerals: get: tags: - SupplyChainService summary: GetCriticalMinerals operationId: GetCriticalMinerals responses: "200": description: Successful response content: application/json: schema: $ref: '#/components/schemas/GetCriticalMineralsResponse' "400": description: Validation error content: application/json: schema: $ref: '#/components/schemas/ValidationError' default: description: Error response content: application/json: schema: $ref: '#/components/schemas/Error' /api/supply-chain/v1/get-shipping-stress: get: tags: - SupplyChainService summary: GetShippingStress description: GetShippingStress returns carrier market data and a composite stress index. operationId: GetShippingStress responses: "200": description: Successful response content: application/json: schema: $ref: '#/components/schemas/GetShippingStressResponse' "400": description: Validation error content: application/json: schema: $ref: '#/components/schemas/ValidationError' default: description: Error response content: application/json: schema: $ref: '#/components/schemas/Error' /api/supply-chain/v1/get-country-chokepoint-index: get: tags: - SupplyChainService summary: GetCountryChokepointIndex description: GetCountryChokepointIndex returns per-chokepoint exposure scores for a country. PRO-gated. operationId: GetCountryChokepointIndex parameters: - name: iso2 in: query description: ISO 3166-1 alpha-2 country code (uppercase). required: false schema: type: string - name: hs2 in: query description: HS2 chapter (2-digit string). Defaults to "27" (energy/mineral fuels) when absent. required: false schema: type: string responses: "200": description: Successful response content: application/json: schema: $ref: '#/components/schemas/GetCountryChokepointIndexResponse' "400": description: Validation error content: application/json: schema: $ref: '#/components/schemas/ValidationError' default: description: Error response content: application/json: schema: $ref: '#/components/schemas/Error' /api/supply-chain/v1/get-bypass-options: get: tags: - SupplyChainService summary: GetBypassOptions description: GetBypassOptions returns ranked bypass corridors for a chokepoint. PRO-gated. operationId: GetBypassOptions parameters: - name: chokepointId in: query required: false schema: type: string - name: cargoType in: query description: 'container | tanker | bulk | roro (default: "container")' required: false schema: type: string - name: closurePct in: query description: '0-100, percent of capacity blocked (default: 100)' required: false schema: type: integer format: int32 responses: "200": description: Successful response content: application/json: schema: $ref: '#/components/schemas/GetBypassOptionsResponse' "400": description: Validation error content: application/json: schema: $ref: '#/components/schemas/ValidationError' default: description: Error response content: application/json: schema: $ref: '#/components/schemas/Error' /api/supply-chain/v1/get-country-cost-shock: get: tags: - SupplyChainService summary: GetCountryCostShock description: GetCountryCostShock returns cost shock and war risk data for a country+chokepoint. PRO-gated. operationId: GetCountryCostShock parameters: - name: iso2 in: query required: false schema: type: string - name: chokepointId in: query required: false schema: type: string - name: hs2 in: query description: 'HS2 chapter (default: "27")' required: false schema: type: string responses: "200": description: Successful response content: application/json: schema: $ref: '#/components/schemas/GetCountryCostShockResponse' "400": description: Validation error content: application/json: schema: $ref: '#/components/schemas/ValidationError' default: description: Error response content: application/json: schema: $ref: '#/components/schemas/Error' /api/supply-chain/v1/get-sector-dependency: get: tags: - SupplyChainService summary: GetSectorDependency description: GetSectorDependency returns dependency flags and risk profile for a country+HS2 sector. PRO-gated. operationId: GetSectorDependency parameters: - name: iso2 in: query required: false schema: type: string - name: hs2 in: query description: HS2 chapter code, e.g. "27" (mineral fuels), "85" (electronics) required: false schema: type: string responses: "200": description: Successful response content: application/json: schema: $ref: '#/components/schemas/GetSectorDependencyResponse' "400": description: Validation error content: application/json: schema: $ref: '#/components/schemas/ValidationError' default: description: Error response content: application/json: schema: $ref: '#/components/schemas/Error' components: schemas: Error: type: object properties: message: type: string description: Error message (e.g., 'user not found', 'database connection failed') description: Error is returned when a handler encounters an error. It contains a simple error message that the developer can customize. FieldViolation: type: object properties: field: type: string description: The field path that failed validation (e.g., 'user.email' for nested fields). For header validation, this will be the header name (e.g., 'X-API-Key') description: type: string description: Human-readable description of the validation violation (e.g., 'must be a valid email address', 'required field missing') required: - field - description description: FieldViolation describes a single validation error for a specific field. ValidationError: type: object properties: violations: type: array items: $ref: '#/components/schemas/FieldViolation' description: List of validation violations required: - violations description: ValidationError is returned when request validation fails. It contains a list of field violations describing what went wrong. GetShippingRatesRequest: type: object GetShippingRatesResponse: type: object properties: indices: type: array items: $ref: '#/components/schemas/ShippingIndex' fetchedAt: type: string upstreamUnavailable: type: boolean ShippingIndex: type: object properties: indexId: type: string name: type: string currentValue: type: number format: double previousValue: type: number format: double changePct: type: number format: double unit: type: string history: type: array items: $ref: '#/components/schemas/ShippingRatePoint' spikeAlert: type: boolean ShippingRatePoint: type: object properties: date: type: string value: type: number format: double GetChokepointStatusRequest: type: object GetChokepointStatusResponse: type: object properties: chokepoints: type: array items: $ref: '#/components/schemas/ChokepointInfo' fetchedAt: type: string upstreamUnavailable: type: boolean ChokepointInfo: type: object properties: id: type: string name: type: string lat: type: number format: double lon: type: number format: double disruptionScore: type: integer format: int32 status: type: string activeWarnings: type: integer format: int32 congestionLevel: type: string affectedRoutes: type: array items: type: string description: type: string aisDisruptions: type: integer format: int32 directions: type: array items: type: string directionalDwt: type: array items: $ref: '#/components/schemas/DirectionalDwt' transitSummary: $ref: '#/components/schemas/TransitSummary' flowEstimate: $ref: '#/components/schemas/FlowEstimate' warRiskTier: type: string enum: - WAR_RISK_TIER_UNSPECIFIED - WAR_RISK_TIER_NORMAL - WAR_RISK_TIER_ELEVATED - WAR_RISK_TIER_HIGH - WAR_RISK_TIER_CRITICAL - WAR_RISK_TIER_WAR_ZONE description: |- * War risk tier derived from Lloyd's JWC Listed Areas + OSINT threat classification. This is a FREE field (no PRO gate) — it exposes the existing server-internal threatLevel from ChokepointConfig, making it available to clients for badges and bypass corridor scoring. DirectionalDwt: type: object properties: direction: type: string dwtThousandTonnes: type: number format: double wowChangePct: type: number format: double TransitSummary: type: object properties: todayTotal: type: integer format: int32 todayTanker: type: integer format: int32 todayCargo: type: integer format: int32 todayOther: type: integer format: int32 wowChangePct: type: number format: double history: type: array items: $ref: '#/components/schemas/TransitDayCount' riskLevel: type: string incidentCount7d: type: integer format: int32 disruptionPct: type: number format: double riskSummary: type: string riskReportAction: type: string TransitDayCount: type: object properties: date: type: string tanker: type: integer format: int32 cargo: type: integer format: int32 other: type: integer format: int32 total: type: integer format: int32 container: type: integer format: int32 dryBulk: type: integer format: int32 generalCargo: type: integer format: int32 roro: type: integer format: int32 capContainer: type: number format: double capDryBulk: type: number format: double capGeneralCargo: type: number format: double capRoro: type: number format: double capTanker: type: number format: double FlowEstimate: type: object properties: currentMbd: type: number format: double baselineMbd: type: number format: double flowRatio: type: number format: double disrupted: type: boolean source: type: string hazardAlertLevel: type: string hazardAlertName: type: string GetCriticalMineralsRequest: type: object GetCriticalMineralsResponse: type: object properties: minerals: type: array items: $ref: '#/components/schemas/CriticalMineral' fetchedAt: type: string upstreamUnavailable: type: boolean CriticalMineral: type: object properties: mineral: type: string topProducers: type: array items: $ref: '#/components/schemas/MineralProducer' hhi: type: number format: double riskRating: type: string globalProduction: type: number format: double unit: type: string MineralProducer: type: object properties: country: type: string countryCode: type: string productionTonnes: type: number format: double sharePct: type: number format: double GetShippingStressRequest: type: object GetShippingStressResponse: type: object properties: carriers: type: array items: $ref: '#/components/schemas/ShippingStressCarrier' stressScore: type: number format: double description: Composite stress score 0–100 (higher = more disruption). stressLevel: type: string description: '"low" | "moderate" | "elevated" | "critical".' fetchedAt: type: integer format: int64 description: 'Warning: Values > 2^53 may lose precision in JavaScript' upstreamUnavailable: type: boolean description: Set to true when upstream data source is unavailable and cached data is stale. ShippingStressCarrier: type: object properties: symbol: type: string description: Ticker or identifier (e.g., "BDRY", "ZIM"). name: type: string description: Human-readable name. price: type: number format: double description: Current price. changePct: type: number format: double description: Percentage change from previous close. carrierType: type: string description: 'Carrier type: "etf" | "carrier" | "index".' sparkline: type: array items: type: number format: double description: 30-day price sparkline. description: ShippingStressCarrier represents market stress data for a carrier or shipping index. GetCountryChokepointIndexRequest: type: object properties: iso2: type: string pattern: ^[A-Z]{2}$ description: ISO 3166-1 alpha-2 country code (uppercase). hs2: type: string description: HS2 chapter (2-digit string). Defaults to "27" (energy/mineral fuels) when absent. required: - iso2 description: GetCountryChokepointIndexRequest specifies the country and optional HS2 chapter. GetCountryChokepointIndexResponse: type: object properties: iso2: type: string description: ISO 3166-1 alpha-2 country code echoed from the request. hs2: type: string description: HS2 chapter used for the computation. exposures: type: array items: $ref: '#/components/schemas/ChokepointExposureEntry' primaryChokepointId: type: string description: Canonical ID of the chokepoint with the highest exposure score. vulnerabilityIndex: type: number format: double description: Composite vulnerability index 0–100 (weighted sum of top-3 exposures). fetchedAt: type: string description: ISO timestamp of when this data was last seeded. description: GetCountryChokepointIndexResponse returns exposure scores for all relevant chokepoints. ChokepointExposureEntry: type: object properties: chokepointId: type: string description: Canonical chokepoint ID from the chokepoint registry. chokepointName: type: string description: Human-readable chokepoint name. exposureScore: type: number format: double description: Exposure score 0–100; higher = more dependent on this chokepoint. coastSide: type: string description: Which ocean/basin side the country's ports face (atlantic, pacific, indian, med, multi, landlocked). shockSupported: type: boolean description: Whether the shock model is supported for this chokepoint + hs2 combination. description: ChokepointExposureEntry holds per-chokepoint exposure data for a country. GetBypassOptionsRequest: type: object properties: chokepointId: type: string cargoType: type: string description: 'container | tanker | bulk | roro (default: "container")' closurePct: type: integer format: int32 description: '0-100, percent of capacity blocked (default: 100)' required: - chokepointId GetBypassOptionsResponse: type: object properties: chokepointId: type: string cargoType: type: string closurePct: type: integer format: int32 options: type: array items: $ref: '#/components/schemas/BypassOption' fetchedAt: type: string primaryChokepointWarRiskTier: type: string enum: - WAR_RISK_TIER_UNSPECIFIED - WAR_RISK_TIER_NORMAL - WAR_RISK_TIER_ELEVATED - WAR_RISK_TIER_HIGH - WAR_RISK_TIER_CRITICAL - WAR_RISK_TIER_WAR_ZONE description: |- * War risk tier derived from Lloyd's JWC Listed Areas + OSINT threat classification. This is a FREE field (no PRO gate) — it exposes the existing server-internal threatLevel from ChokepointConfig, making it available to clients for badges and bypass corridor scoring. BypassOption: type: object properties: id: type: string name: type: string type: type: string addedTransitDays: type: integer format: int32 addedCostMultiplier: type: number format: double capacityConstraintTonnage: type: string format: int64 suitableCargoTypes: type: array items: type: string activationThreshold: type: string waypointChokepointIds: type: array items: type: string liveScore: type: number format: double bypassWarRiskTier: type: string enum: - WAR_RISK_TIER_UNSPECIFIED - WAR_RISK_TIER_NORMAL - WAR_RISK_TIER_ELEVATED - WAR_RISK_TIER_HIGH - WAR_RISK_TIER_CRITICAL - WAR_RISK_TIER_WAR_ZONE description: |- * War risk tier derived from Lloyd's JWC Listed Areas + OSINT threat classification. This is a FREE field (no PRO gate) — it exposes the existing server-internal threatLevel from ChokepointConfig, making it available to clients for badges and bypass corridor scoring. notes: type: string GetCountryCostShockRequest: type: object properties: iso2: type: string pattern: ^[A-Z]{2}$ chokepointId: type: string hs2: type: string description: 'HS2 chapter (default: "27")' required: - iso2 - chokepointId GetCountryCostShockResponse: type: object properties: iso2: type: string chokepointId: type: string hs2: type: string supplyDeficitPct: type: number format: double description: Average refined-product supply deficit % under full closure (Gasoline/Diesel/Jet fuel/LPG average; HS 27 only) coverageDays: type: integer format: int32 description: Energy stockpile coverage in days (IEA data, HS 27 only; 0 for non-energy sectors or net exporters) warRiskPremiumBps: type: integer format: int32 description: War risk insurance premium in basis points for this chokepoint warRiskTier: type: string enum: - WAR_RISK_TIER_UNSPECIFIED - WAR_RISK_TIER_NORMAL - WAR_RISK_TIER_ELEVATED - WAR_RISK_TIER_HIGH - WAR_RISK_TIER_CRITICAL - WAR_RISK_TIER_WAR_ZONE description: |- * War risk tier derived from Lloyd's JWC Listed Areas + OSINT threat classification. This is a FREE field (no PRO gate) — it exposes the existing server-internal threatLevel from ChokepointConfig, making it available to clients for badges and bypass corridor scoring. hasEnergyModel: type: boolean description: Whether supply_deficit_pct and coverage_days are modelled (true) or unavailable (false) unavailableReason: type: string description: Null/unavailable explanation for non-energy sectors fetchedAt: type: string GetSectorDependencyRequest: type: object properties: iso2: type: string pattern: ^[A-Z]{2}$ hs2: type: string description: HS2 chapter code, e.g. "27" (mineral fuels), "85" (electronics) required: - iso2 - hs2 GetSectorDependencyResponse: type: object properties: iso2: type: string hs2: type: string hs2Label: type: string description: Human-readable HS2 chapter name. flags: type: array items: type: string enum: - DEPENDENCY_FLAG_UNSPECIFIED - DEPENDENCY_FLAG_SINGLE_SOURCE_CRITICAL - DEPENDENCY_FLAG_SINGLE_CORRIDOR_CRITICAL - DEPENDENCY_FLAG_COMPOUND_RISK - DEPENDENCY_FLAG_DIVERSIFIABLE description: DependencyFlag classifies how a country+sector dependency can fail. primaryExporterIso2: type: string description: ISO2 of the country supplying the largest share of this sector's imports. primaryExporterShare: type: number format: double description: Share of imports from the primary exporter (0–1). 0 = no Comtrade data available. primaryChokepointId: type: string description: Chokepoint ID with the highest exposure score for this country+sector. primaryChokepointExposure: type: number format: double description: Exposure score for the primary chokepoint (0–100). hasViableBypass: type: boolean description: Whether at least one viable bypass corridor exists for the primary chokepoint. fetchedAt: type: string