conversation_id to start a new conversation, or pass one to continue an existing one.
Request
Send an
Idempotency-Key header to make a request safe to retry and to poll. Since natural language requests return immediately with 202 Accepted, an Idempotency Key is required to retrieve the final result. See Limits.
Natural language input
Structured input
Structured input is a set ofkey: value lines — one variable per line — plus a calculate: line naming the variable to solve for. For the full grammar — values, units, tables, scenario selectors, and how omitted lines are inferred — see Input formats.
JSON input
A JSON request setsinput_format to json and passes a JSON string as prompt. Like structured text, it involves no language model and runs synchronously — the result returns in the same response. For the full object — inputs, calculate, scenario, and value conventions — see Input formats.
prompt that parses as JSON but does not match the schema returns input.invalid_input_schema; a prompt that is not valid JSON returns the transport error error_invalid_json.
Automatic detection
Setinput_format to automatic — or leave it out, or pass null or "" — to let TrueMath determine from the prompt whether it is natural language, structured text, or JSON, and process it accordingly. This is the default when the field is absent.
natural_language is processed asynchronously, while one detected as structured or json runs synchronously. Specify input_format explicitly when you already know the format and want to skip detection.
Time zones
A stored date or clock time carries no time zone and never shifts. A value meaning 2:30 PM on July 21st reads as 2:30 PM on July 21st for every caller, in every country: it is never re-projected into a viewer’s zone and shown as 5:30 PM. That is why the UTC pin under Dates and durations renders one correctly — there is no zone to convert from. A zone is used for one thing, and has no other effect: reading whattoday and now mean at the moment a calculation runs and, with them, what year a date written without one falls in.
Two things supply that zone:
-
The request. Over the API that is the
time_zoneparameter, an IANA name such asAmerica/New_York. In the Playground it is the browser’s own zone, sent with each calculation — never a timestamp, so a device with a wrong clock cannot move what today is. Either way the zone is applied once per request, so every keyword in one calculation agrees. - Your account’s time zone, when the request supplies none or names a zone that is not recognized. That covers the API, an integration, and a scheduled job.
Response
The response echoes the conversation, message, and request metadata, and reports its outcome withstatus. A completed or error outcome returns 200 OK; an asynchronous request that is still running returns 202 Accepted with status: "in_progress".
The echo of your input depends on the format. A
structured request returns its result as structured_text. A natural_language request returns the natural_language reading plus the parsed input as parsed_json. A json request returns the parsed input as parsed_json. structured_text is always a key on a completed response — null for natural_language and json — while natural_language and parsed_json are present only for the formats noted above and omitted otherwise.
Completed
A completed calculation returnsstatus: "completed" and a results object: the action taken, the scenario indexes, the activities applied, and every variable with its value, provenance, and display format. results.calculated is the id of the variable that was solved for (null when action is fetch).
key is its creator-defined variable name. source is user_input, calculated, or default_value, and historical indicates whether the value was carried forward from a prior scenario. value is a combined "value unit" string at full precision — the unit is part of the value string (see Units and precision). For a table, value is an array of such strings (nested for a 2-D table); see Tables.
The scenario object reports the original scenario the calculation started from (0 starts a new scenario) and the current scenario the results belong to. action is one of new, extend, discard, or fetch — see Scenarios. When action is fetch, retrieve that scenario with GET /v1/conversations/:id/context.
Display formats
Each variable carries adisplay object. data_type selects its shape — number, table, bar_chart, or pie_chart — and the remaining fields depend on it. It names the shape of the object, not the kind of the value: a date, a percent, and a plain number all arrive as number, and display_type is what tells them apart. Two fields recur across shapes:
number — any single value: a scalar or unit number, a percent, or one of the four dates and durations.
table — a grid with per-column formats and optional row names.
bar_chart — a table presented as a bar chart.
The
series array above names each series (name) and says how its values are formatted (display_type and decimal_format). It should match the number of series in the variable’s value itself. What each of these settings does to the chart is in Authoring charts.
series_by describes whether each series is a row or a column of the table. A database, for instance, generally holds its series in columns.
When labels.source is index, all data from the table is plotted and the x-axis labels are derived as integers starting with start_series_index.
When labels.source is first_series, the first series in the table is used as the x-axis labels instead and not included in the chart’s plotted bars. How that data is formatted is derived from the metadata within series[0]. Your first plotted bar is therefore the second series, described by series[1].
pie_chart — a table presented as a pie chart.
Dates and durations
Adisplay_type of duration, date, datetime, or time marks a value stored as a count of seconds carrying the unit s. The API renders nothing: the number arrives with its kind and its format token beside it, and you render it yourself.
- Seconds, not milliseconds.
new Date(1784592000)is 1970-01-21. Multiply by 1000. - Format in UTC. The number is a naive wall clock — its components are the value, and it is not an instant in any particular zone. A zone-aware formatter moves the day.
- Branch on
display_type. It changes the arithmetic, not just the format. Adurationis a span with no date involved and never becomes a date. Atimecounts from midnight, which is the same number on 1970-01-01, so a UTC-pinned time-only format works. Adateand adatetimecount from the epoch.
Chart scaling
A chart whose cells carry different units of the same dimension —3 ft, 4 in, 5 yd — is drawn to one common unit, so its bars and slices are proportioned honestly; see Mixed units in a chart. The API renders nothing, so it hands you those converted magnitudes: the variable carries them alongside value and display, in these fields. They are present only when relevant. value is unchanged and is what labels and tooltips are drawn from.
A chart variable is in exactly one of three states:
- Scaled —
scaleandscale_unitare present. Plot fromscale, label the axis withscale_unit, and show the originalvaluecell in tooltips. - Incompatible —
scale_incompatibleandscale_typesare present. There is no common axis; render a short message instead of a chart. - Neither — no scale fields. The column is a single unit or unitless; plot the numeric part of each
valuecell directly, with the first cell’s unit as the axis unit.
scale values are full precision — format them with the variable’s display decimal settings, the same as value.
3, 0.333, and 15 on a ft axis, while the second bar’s tooltip reads 4 in — the original authored value, not 0.333 ft. When the cells span different dimensions, no chart is drawn:
In progress
Natural-language requests will be processed asynchronously; structured-text and JSON requests run synchronously and never returnin_progress. When a natural-language request is still running, the API responds with 202 Accepted, status: "in_progress" and no results:
Idempotency-Key until status is completed or error. Leave a 1–2 second gap between retries. This could take multiple retries but rarely more than 20 total. You can also poll the conversation with GET /v1/conversations/:id.
Error
A calculation that cannot complete returnsstatus: "error" with an errors array. Each entry has a code and message, plus conditionally included args, offset, and missing fields (present only when the error uses them).
args, offset, and missing contain, and the full list of calculation error codes.
Transport errors
Problems with the request itself — rather than with the calculation — return a4xx or 5xx status and a single error object:

