REST API Documentation

REST API Documentation

All OTTO services expose RESTful APIs with JSON responses. Each service includes rate limiting, work queue backpressure, CORS support, and Prometheus metrics. "Try in Browser" demos run locally via WASMโ€”the same C code powers both server and browser thanks to transport-agnostic design.

Common Endpoints (All Services)

GET /api/v1/health
GET /api/v1/stats
GET /metrics
GET /api/v1/health Health check (bypasses rate limit and queue)

Response

{
  "status": "healthy",
  "service": "carta",
  "version": "1.0.0"
}
WASM Try it in browser

                                
GET /api/v1/stats Server statistics (bypasses queue)

Response

{
  "service": "carta",
  "work_queue": {
    "enabled": true,
    "depth": 5,
    "capacity": 256,
    "pushed": 1234,
    "popped": 1230,
    "dropped": 2,
    "expired": 2
  },
  "rate_limit": {
    "enabled": true,
    "rps": 10.0,
    "burst": 100,
    "allowed": 5678,
    "denied": 42
  }
}
WASM Try it in browser

                                
GET /metrics Prometheus metrics

Response

# HELP carta_requests_total Total HTTP requests
# TYPE carta_requests_total counter
carta_requests_total{status="200"} 1234
carta_requests_total{status="404"} 12
# HELP carta_request_duration_ms Request duration in milliseconds
# TYPE carta_request_duration_ms histogram
carta_request_duration_ms_bucket{le="10"} 500
carta_request_duration_ms_bucket{le="50"} 1100
carta_request_duration_ms_bucket{le="100"} 1200
๐Ÿ—บ๏ธ
Carta Tile Server
Default port: 8081

Serves vector tiles (MVT), raster tiles (PNG), and ASCII art tiles from OSM PBF files. Compatible with Leaflet, MapLibre, Google Maps, and OpenLayers.

GET /tiles/{z}/{x}/{y}.png Raster tile (PNG)

Path Parameters

Name Type Description
z required int Zoom level (0-18)
x required int Tile X coordinate
y required int Tile Y coordinate

Example

# Get tile at zoom 14, Monaco area
curl http://localhost:8081/tiles/14/8529/5974.png -o tile.png

Response

PNG image (512x512 by default). Content-Type: image/png

WASM Try it in browser

Generate a tile using Carta WASM with embedded Monaco data. No server required.

GET /tiles/{z}/{x}/{y}.mvt Vector tile (MVT/Protobuf)

Path Parameters

Name Type Description
z required int Zoom level (0-18)
x required int Tile X coordinate
y required int Tile Y coordinate

Response

Mapbox Vector Tile format. Use with MapLibre GL JS or similar vector tile renderers.

WASM Try it in browser

Generate MVT vector tile using WASM (shows size info)


                                
GET /tiles/{z}/{x}/{y}.txt ASCII art tile

Path Parameters

Name Type Description
z required int Zoom level
x required int Tile X coordinate
y required int Tile Y coordinate

Query Parameters

Name Type Description
width int Output width in characters (20-400, default: 80) (default: 80)
height int Output height (0=auto from aspect ratio) (default: 0)
charset string simple, extended (default), blocks, braille (default: extended)
invert bool 1 for light background terminals (default: 0)
color bool 1 for ANSI 256-color output (default: 0)

Example

# ASCII map in terminal
curl "http://localhost:8081/tiles/14/9058/5729.txt?width=120&charset=blocks"

Response

ASCII art representation of the tile

WASM Try it in browser

Render ASCII art map tile using WASM


                                
GET /tiles.json TileJSON metadata

Response

{
  "tilejson": "3.0.0",
  "name": "OTTO Carta",
  "description": "Map tiles generated by Carta",
  "version": "1.0.0",
  "attribution": "OpenStreetMap contributors",
  "scheme": "xyz",
  "tiles": ["http://localhost:8081/tiles/{z}/{x}/{y}.png"],
  "vector_tiles": ["http://localhost:8081/tiles/{z}/{x}/{y}.mvt"],
  "minzoom": 0,
  "maxzoom": 18,
  "bounds": [7.41, 43.72, 7.44, 43.75],
  "center": [7.42, 43.73, 10]
}
WASM Try it in browser

Fetch TileJSON metadata from embedded Monaco data.


                                
๐Ÿ›ฃ๏ธ
Velo Route Server
Default port: 8082

Route planning between coordinates with vehicle profiles, optimization modes, and Google Polyline encoded geometry. Uses A* with Landmarks for fast queries.

GET /api/v1/route Calculate route between coordinates

Query Parameters

Name Type Description
profile string Vehicle profile: car, truck, bike, foot (default: car)
mode string Optimization: fastest (time) or shortest (distance) (default: fastest)
geometry bool Include Google Polyline encoded geometry (default: false)

Example

# Calculate fastest car route between Budapest and Szeged
curl "http://localhost:8082/api/v1/route?from=47.5,19.0&to=46.2,20.1&profile=car&mode=fastest"

Response

{
  "status": "ok",
  "route": {
    "distance": 187432.5,
    "duration": 7234.2,
    "profile": "car",
    "mode": "fastest",
    "from": [47.497, 19.040],
    "to": [46.253, 20.148],
    "geometry": "encoded_polyline..."
  },
  "meta": {
    "nodes_explored": 12543,
    "search_time_ms": 34.5
  }
}
WASM Try it in browser

Calculate a route in Monaco using WASM


                                
POST /api/v1/route Calculate route between coordinates (JSON body)

Response

{
  "status": "ok",
  "route": {
    "distance": 187432.5,
    "duration": 7234.2,
    "profile": "car",
    "mode": "fastest",
    "from": [47.497, 19.040],
    "to": [46.253, 20.148],
    "geometry": "encoded_polyline..."
  }
}
GET /api/v1/health Health check endpoint

Response

{
  "status": "healthy",
  "service": "velo-route-server",
  "version": "1.0.0"
}
WASM Try it in browser

Check WASM health status


                                
GET /api/v1/stats Graph and server statistics

Response

{
  "graph_path": "/data/hungary.osm.pbf",
  "num_nodes": 2745632,
  "num_edges": 5891234,
  "landmarks_enabled": true,
  "landmark_count": 32,
  "bbox": {
    "min_lat": 45.74,
    "min_lon": 16.11,
    "max_lat": 48.58,
    "max_lon": 22.90
  }
}
WASM Try it in browser

Get Monaco graph statistics


                                
GET /metrics Prometheus metrics endpoint

Response

Prometheus exposition format metrics

๐Ÿ“
Locus Geocoder
Default port: 8083

Forward geocoding (text search), autocomplete, and reverse geocoding (coordinate to address). Uses trie + trigram index for fast fuzzy matching.

GET /api/v1/search Forward geocoding - search for places by name

Query Parameters

Name Type Description
limit int Maximum results (1-100) (default: 10)

Example

# Search for "Monte Carlo" with max 5 results
curl "http://localhost:8083/api/v1/search?q=Monte%20Carlo&limit=5"

Response

{
  "query": "Monte Carlo",
  "total": 5,
  "took_ms": 0.12,
  "results": [
    {
      "osm_id": 12345,
      "osm_type": "node",
      "name": "Monte Carlo",
      "class": "place",
      "lat": 43.7396,
      "lon": 7.4269,
      "score": 1.0
    }
  ]
}
WASM Try it in browser

Search Monaco places using WASM with embedded index


                                
GET /api/v1/autocomplete Autocomplete suggestions for partial input

Query Parameters

Name Type Description
limit int Maximum suggestions (1-20) (default: 10)

Example

# Get autocomplete suggestions for "Mon"
curl "http://localhost:8083/api/v1/autocomplete?q=Mon&limit=10"

Response

[
  "Monaco",
  "Monte Carlo",
  "Moneghetti"
]
WASM Try it in browser

Autocomplete suggestions using WASM with embedded Monaco index


                                
GET /api/v1/reverse Reverse geocoding - find address for coordinates

Example

# Reverse geocode coordinates in Monaco
curl "http://localhost:8083/api/v1/reverse?lat=43.7384&lon=7.4246"

Response

{
  "lat": 43.7384,
  "lon": 7.4246,
  "display_name": "Avenue de Monte-Carlo, Monaco",
  "distance_m": 45.2,
  "place": "Monaco",
  "street": "Avenue de Monte-Carlo"
}
WASM Try it in browser

Reverse geocode a Monaco location using WASM


                                
GET /api/v1/health Health check endpoint

Response

{
  "status": "healthy",
  "service": "locus",
  "version": "0.1.0"
}
WASM Try it in browser

Check WASM health status


                                
GET /api/v1/stats Index and server statistics

Response

{
  "entities": 2763,
  "memory_mb": 7.8,
  "bounds": {
    "min_lat": 43.7234,
    "min_lon": 7.4089,
    "max_lat": 43.7519,
    "max_lon": 7.4398
  },
  "rate_limit": {
    "enabled": true,
    "rps": 50.0,
    "burst": 100
  },
  "work_queue": {
    "enabled": true,
    "depth": 5,
    "capacity": 128
  }
}
WASM Try it in browser

Get Monaco index statistics


                                
GET /metrics Prometheus metrics endpoint

Response

Prometheus exposition format metrics

โ›ฝ
FuelWise Optimizer
Default port: 8080

Refueling optimization using Linear Programming. Finds minimum-cost fuel stops along a route considering tank capacity, fuel prices, and consumption patterns.

POST /api/v1/solve Solve a refueling optimization problem

Request Body (JSON)

{
  "total_distance": 1000,
  "tank_capacity": 100,
  "current_fuel": 50,
  "consumption_mpg": 10,
  "minimum_fuel": 10,
  "stations": [
    {"id": 1, "distance": 200, "price": 1.20},
    {"id": 2, "distance": 500, "price": 1.00},
    {"id": 3, "distance": 700, "price": 1.30}
  ]
}

Response

{
  "status": "OPTIMAL",
  "num_stops": 2,
  "total_cost": 68.00,
  "gross_cost": 68.00,
  "remaining_fuel": 10.00,
  "stops": [
    {"station_id": 1, "gallons": 30.00, "cost": 36.00},
    {"station_id": 2, "gallons": 30.00, "cost": 30.00}
  ]
}
WASM Try it in browser

Solve a refueling problem using LP optimization in WASM. No server required.


                                
POST /api/v1/filter Filter fuel stations to those near a route

Response

{
  "count": 3,
  "stations": [
    {
      "station_id": 1,
      "distance_from_start": 45.2,
      "perpendicular_distance": 0.8,
      "price_per_gallon": 3.45,
      "snap_point": [34.0522, -118.2437]
    }
  ]
}
POST /api/v1/optimize Full optimization pipeline: filter stations and solve refueling

Response

{
  "status": "OPTIMAL",
  "route_distance": 487.5,
  "stations_filtered": 5,
  "num_stops": 2,
  "total_cost": 245.50,
  "gross_cost": 245.50,
  "remaining_fuel": 28.3,
  "stops": [
    {"station_id": 3, "distance_from_start": 125.4, "gallons": 42.0, "cost": 142.80},
    {"station_id": 7, "distance_from_start": 356.2, "gallons": 35.5, "cost": 102.70}
  ]
}
GET /api/v1/health Health check endpoint

Response

{
  "status": "healthy",
  "service": "fuelwise-api",
  "version": "1.0.0"
}
WASM Try it in browser

Check FuelWise API health status


                                
GET /api/v1/stats Server statistics endpoint

Response

{
  "service": "fuelwise-api",
  "version": "1.0.0",
  "work_queue": {
    "enabled": true,
    "depth": 0,
    "capacity": 100
  },
  "rate_limit": {
    "enabled": true,
    "rps": 10.0,
    "burst": 100.0
  }
}
WASM Try it in browser

View FuelWise server statistics


                                
๐Ÿ“
Ralph LP/MIP Solver
Default port: 8084

Linear and Mixed-Integer Programming solver. Supports LP format input with simplex, branch-and-bound, LAP, and network flow algorithms.

POST /api/v1/solve Solve LP/MIP problem

Query Parameters

Name Type Description
format string Input format: "lp", "mps", or "json" (default: lp) (default: lp)
timeout_ms int Timeout in milliseconds (max 30000) (default: 5000)

Example

curl -X POST "http://localhost:8084/api/v1/solve?format=lp" -d @problem.lp

Request Body (LP Format)

max: 5 x + 3 y

subject to
wood:  2 x + 4 y <= 40
labor: 3 x + 2 y <= 24

bounds
x >= 0
y >= 0

end

Response (Text)

solution status: OPTIMAL
objective value: 40.000000
x 8.000000
y 0.000000
WASM Try it in browser

Solve a small LP problem using Ralph WASM. No server required.


                                
GET /api/v1/formats List supported input formats

Response

{
  "formats": [
    {"id": "lp", "name": "CPLEX LP", "description": "CPLEX LP file format"},
    {"id": "mps", "name": "MPS", "description": "Mathematical Programming System format"}
  ]
}
WASM Try it in browser

Get supported formats


                                
GET /api/v1/health Health check

Response

{"status": "ok", "version": "1.0.0"}
๐Ÿ“ฆ
Surge VRP Solver
Default port: 8085

Rich Vehicle Routing Problem solver using ALNS metaheuristics. Supports VRPTW, PDPTW, DARP with time windows, capacity, compartments, and precedence constraints.

POST /api/v1/solve Solve a Vehicle Routing Problem

Request Body (JSON)

{
  "vehicles": [
    {"id": 0, "depot_start": 0, "depot_end": 0,
     "capacity": [20], "shift": [0, 1000]}
  ],
  "depots": [
    {"id": 0, "x": 40.0, "y": 50.0, "tw": [0, 1000]}
  ],
  "tasks": [
    {"id": 0, "x": 45.0, "y": 55.0, "tw": [0, 500], "service": 10, "demand": [5]},
    {"id": 1, "x": 42.0, "y": 58.0, "tw": [0, 500], "service": 10, "demand": [3]},
    {"id": 2, "x": 38.0, "y": 52.0, "tw": [100, 800], "service": 10, "demand": [4]}
  ],
  "requests": [
    {"id": 0, "delivery_task": 0},
    {"id": 1, "delivery_task": 1},
    {"id": 2, "delivery_task": 2}
  ],
  "config": {"max_iterations": 1000}
}

Response

{
  "status": "OK",
  "stats": {
    "iterations": 1000,
    "total_cost": 12345.67,
    "total_distance": 828.94,
    "unassigned": 0,
    "vehicles_used": 1
  }
}
WASM Try it in browser

Solve a VRP problem using WASM


                                
GET /api/v1/health Health check endpoint

Response

{
  "status": "healthy",
  "service": "surge",
  "version": "0.1.0-dev"
}
WASM Try it in browser

Check Surge health status


                                
GET /api/v1/stats Statistics and status

Response

{
  "service": "surge",
  "version": "0.1.0-dev",
  "status": "OK"
}
GET /api/v1/version Version information

Response

{
  "version": "0.1.0-dev"
}

HTTP Status Codes

200 Success
400 Bad Request
404 Not Found
405 Method Not Allowed
422 Infeasible Problem
429 Rate Limited
500 Server Error
503 Queue Full
504 Request Timeout