TopoStackGuides
Browse guides

Project request and HTTP API reference

The model request every TopoStack agent tool accepts, the studio links it becomes, and the HTTP routes that let a script plan models without an MCP client.

The MCP server and the HTTP API run the same code. A request means the same thing on either one, and both return the same plans and links. Neither generates files: a response ends in a studio link, and the model is generated and exported in the browser that opens it.

The project request

A request describes the model in physical terms. Only requestVersion and area are required. Every other field falls back to the studio's default, and unknown fields are rejected. The MCP tools assume requestVersion: 1 when it is left out; the HTTP routes require it. The JSON Schema is embedded in the OpenAPI document and is also served as the MCP resource topostack://schema/project-request-v1.

{
  "requestVersion": 1,
  "area": {
    "center": {
      "lat": 39.09,
      "lon": -120.04
    },
    "widthKm": 30
  },
  "placeLabel": "Lake Tahoe, California and Nevada",
  "output": "layered",
  "widthMm": 400,
  "heightMm": 300,
  "materialThicknessMm": 3,
  "verticalExaggeration": 2,
  "details": {
    "roads": false,
    "boundaries": true
  },
  "title": "LAKE TAHOE\n39.09° N 120.04° W",
  "laser": {
    "kerfMm": 0.15,
    "workAreaWidthMm": 400,
    "workAreaHeightMm": 400
  },
  "markers": [
    {
      "lat": 38.9533,
      "lon": -119.9442,
      "name": "South Lake Tahoe",
      "symbol": "star"
    }
  ]
}
FieldRange or optionsDefaultNotes
requestVersion1Required on HTTP routes
area{ center: { lat, lon }, widthKm } or { bounds: { west, south, east, north } }See the notes below.
placeLabelUp to 240 charactersCustom coordinatesShown in the studio, for example a label from place search
nameUp to 120 charactersThe part of placeLabel before the first commaAlso names the exported files
outputlayered, flatlayeredA stack of cut sheets, or contour lines engraved on one sheet
widthMm, heightMm20–10,000300 × 200The finished model
shaperectangle, circlerectangle
unitsmetric, imperialmetricFor engraved labels and the scale bar; files are always in millimeters
materialThicknessMm0.5–253Layered. Thicker material gives fewer, coarser layers.
verticalExaggeration1–102Layered. It is refitted so the stack is a whole number of sheets.
contourCountWhole number, 4–4012Flat. Engraved contour lines across the elevation range.
detailswater, waterDepth, roads, trails, roadLabels, boundaries, coordinateGrid, elevationLabels, northArrow, scaleBar (true or false)On: water, water depth, roads, trails, elevation labels, north arrow, scale bar. Off: road labels, boundaries, coordinate grid.Keys left out keep their default
titleUp to 3 lines of 40 characters, separated by \nNoneAn empty string removes the title
laser.kerfMm0–10.15Kerf compensation for the cut lines
laser.workAreaWidthMm, laser.workAreaHeightMm0, or 20–10,0000 (unlimited)A model larger than the bed is split into pieces with alignment tabs
markersUp to 20 of { lat, lon, name?, symbol? }NoneNames up to 60 characters. Symbols: pin (default), circle, triangle, star, cross.

Notes on the area:

  • widthKm is the ground distance from west to east, from 0.1 to 2,000 km.
  • With bounds, the whole box stays in view, and the crop is fitted to the model's proportions.
  • Latitudes must lie within ±85.0511°, the limit of Web Mercator.
  • An area cannot cross the antimeridian: west must be less than east.

Notes on text fields:

  • Control characters, and invisible characters such as zero-width or bidirectional marks, are removed.
  • Runs of whitespace are collapsed.

Fonts, line styles, custom graphics, GPS tracks and depth charts are not part of the request. The person sets them in the studio after opening the link. For what each setting does, see the studio settings reference.

Studio links

A studio link has the form https://topostack.app/studio?generate=1#p=1.<design>. The whole design is compressed into the part after #, which browsers never send to a server. Opening the link does three things:

  • It loads the design as one undoable change, so Undo brings back the project that was open before.
  • It starts generating straight away.
  • It removes the design from the address bar, so a refresh does not generate again.

The same request always gives the same link. Links are limited to 8,000 characters. A request normally fits easily; a complete project with a lot of custom data may not, and is then refused with a message saying so.

HTTP routes

The OpenAPI 3.1 document at https://topostack.app/v1/openapi.json describes every route. POST bodies are JSON (content-type: application/json) of at most 128,000 bytes.

RouteTakesReturns
POST /v1/projects/resolveA project requestThe complete studio project the request expands to, its studioUrl, and attribution
POST /v1/projects/planA project requestThe same plan as the plan_model tool: the project summary, the sheet count, the stack height, fitted exaggeration, scale, elevation range, coverage, notes, studioUrl and attribution
POST /v1/projects/linkA project request, or { "project": … } holding a complete studio projecturl and length
GET /v1/coverage?bbox=west,south,east,north or ?lat=…&lon=…&widthKm=…High-resolution terrain and lake surveys covering the area, with attribution
GET /v1/geocode?q= (2–160 characters) and optional limit (1–8)Place search results
GET /v1/openapi.jsonThe OpenAPI document

For example, to plan a model:

curl -s -X POST https://topostack.app/v1/projects/plan \
  -H 'content-type: application/json' \
  -d '{"requestVersion":1,"area":{"center":{"lat":46.8523,"lon":-121.7603},"widthKm":20},"placeLabel":"Mount Rainier"}'

To make a link for a project saved from the studio, rather than for a request:

curl -s -X POST https://topostack.app/v1/projects/link \
  -H 'content-type: application/json' \
  -d @- <<'EOF'
{ "project": <the project from a saved TopoStack project file> }
EOF

Errors

Errors are JSON with an error message. A 422 for a request also lists each invalid field:

{
  "error": "The project request is invalid.",
  "errors": [
    {
      "path": "materialThicknessMm",
      "message": "Must be between 0.5 and 25."
    }
  ]
}
StatusWhen
400The body is not valid JSON, or the coverage query is malformed
405The wrong method for the route
413The body is over 128,000 bytes, or the design does not fit in an 8,000-character link
415The body is not sent as application/json
422The request or project is invalid
429A rate limit, below. Retry after the retry-after seconds. On a plan, "The terrain budget for this client is used up" means the terrain tiles, not the request budget, ran out.
502Terrain could not be fetched for a plan, or place search failed. Try again shortly.
503, 504Place search is not configured on this server, or timed out.

Limits

  • No key or account is needed.
  • The POST routes share a budget with the MCP server: 120 requests a minute per address, and a shared ceiling of 1,200 a minute.
  • A plan reads at most four low-resolution terrain tiles. When those are not cached, they also count against the terrain budget.
  • Place search has its own budget of 30 uncached searches a minute per address.
  • Responses allow any origin, so browser code on another site can call the API.

How accurate a plan is

A plan samples coarse terrain, which smooths sharp peaks. Lake depth can also add sheets that only full generation counts. Measured against the studio, plans agree within a sheet or two, for example:

  • Mount Rainier: 35 planned, 36 generated;
  • Lake Tahoe: 9 and 9;
  • the Matterhorn: 45 and 45.

The count the studio shows after generating is the one that is cut. Output is decorative, not survey-grade.

A plan's notes are plain sentences worth showing to the person. The first always says the count is an estimate. Others appear when the ground is nearly flat, when a layered stack passes 60 sheets, when the area reaches the sea (the sea is cut flat and the stack is sized from the land), when surveyed lake depth will add sheets below the shoreline, and when the model is larger than the laser bed, so each sheet is split into pieces with alignment tabs.

Data and credit

Every plan, link and coverage response includes an attribution object for the terrain, map and lake data it used. Keep its credit line with anything shown or passed on. The full list of sources and licenses is on the attribution page, and the privacy notice covers what the API receives.

Create a topographic map