The API response
Updated 2026-11-13
What a successful call returns: the four parts of the JSON answer, the shapes an output value can have, the flatten option, and the CSV and plain-text formats for spreadsheets.
The answer at a glance
{
"service": { "id": "{serviceId}", "name": "Loan", "description": "Yearly interest of a loan" },
"inputs": [
{ "name": "amount", "title": "Amount", "value": 20000 },
{ "name": "rate", "title": "Rate", "value": 0.05 }
],
"outputs": [
{ "name": "interest", "title": "Interest", "value": 1000, "formatString": "#,##0.00" }
],
"metadata": {
"executionTime": 12,
"totalTime": 15,
"timestamp": "2026-11-13T09:00:00.000Z",
"version": "v1"
}
}GET and POST return the same shape. The HTTP status of a successful call is 200.
service
id: the service ID.name: the service name, ornull.description: the description of the service, ornull.
inputs
A list of the values the calculation used: the ones you sent and the defaults that were filled in. Each entry has name, title and value. Use it to confirm what the service understood, for example that 0.05 arrived as the rate.
outputs
A list with one entry per output of the service, in the order of the service definition. Each entry has:
name: the output's name. Use it as the key in your code.title: the readable label.value: the result.formatString: the Excel number format of the cell, when it has one.
outputs is a list, not an object. To read one result, find the entry by name, or ask for the flat form with flatten=true.
What a value can be
| Output | value |
|---|---|
| A single cell with a number | A number, unrounded |
| A single cell with text | A text |
| A single cell with TRUE or FALSE | true or false |
| An empty cell | null |
| A cell range | A table: a list of rows, each row a list of cell values. A range on a formula that fills several cells has as many rows as the formula fills for this call; any other range has the size the owner selected |
| A cell with a formula error | The error as text, for example "#VALUE!" or "#DIV/0!" |
Numbers come as raw values. A cell that shows 5.00% returns 0.05, and a cell that shows 1,000.00 returns 1000. formatString tells you how the cell is formatted, so you can show the value the same way; see Percentages and formats.
A formula error in an output is still a successful call with status 200. Check the value if your workbook can produce errors for some inputs.
Tables
A cell range comes back as a list of rows.
- Size. The number of rows is fixed for a plain range. A range on a formula that fills several cells, such as
SEQUENCEorFILTER, has as many rows and columns as the formula fills for the inputs of the call, so read the table by its length. - Limit. A table that follows its formulas has at most 10,000 cells. If rows were left out, the output carries
"truncated": true. - `columnFormats` is the number format of each column,
""for a column without one. The values themselves are raw. - `hasHeaderRow` is
truewhen the first row holds the column titles.
The owner's side of this is described in Add outputs.
metadata
Timing and cache details of the call:
executionTime: the calculation time in milliseconds.totalTime: the total time on the server in milliseconds.timestamp: when the answer was made.version:v1.cached:truewhen the answer came from a stored result. See Caching and performance.exportUrl: a link to the filled-in workbook, when the service allows Excel export. See Export a workbook.
More fields may appear in metadata. Do not build on fields that are not listed here.
flatten: the outputs by name
Add flatten=true to the address and the answer also carries result, one object with the output names as keys:
curl -X POST "https://spreadapi.io/api/v1/services/{serviceId}/execute?flatten=true" \
-H "Content-Type: application/json" \
-d '{"inputs": {"amount": 20000, "rate": 0.05}}'{
"service": { ... },
"inputs": [ ... ],
"outputs": [ { "name": "interest", "title": "Interest", "value": 1000 } ],
"result": { "interest": 1000 },
"metadata": { ... }
}flatten is a parameter of the address, not a field of the body. The outputs list stays in the answer. An output without a value appears as null in result.
CSV and plain text
On GET, _format changes the answer for spreadsheet formulas:
_format | Content type | Answer |
|---|---|---|
json (default) | application/json | The JSON described above |
csv | text/csv | Two lines: the output names, then the values, separated by commas |
plain | text/plain | One line per output: name: value |
GET https://spreadapi.io/api/v1/services/{serviceId}/execute?amount=20000&rate=0.05&_format=csvinterest,total 1000,21000
GET https://spreadapi.io/api/v1/services/{serviceId}/execute?amount=20000&rate=0.05&_format=plaininterest: 1000 total: 21000
CSV and plain text carry only the outputs, and they are made for single-cell outputs. For cell ranges and for text that contains commas, use JSON. _format works on GET only. An error is always answered as JSON, whatever the format.
_pretty=true on GET returns the JSON indented, which is easier to read in a browser.
Related
For developers and agents
Top-level fields of a successful answer:
| Field | Type | Notes |
|---|---|---|
service | object | id, name (nullable), description (nullable) |
inputs | array | {name, title, value} per input the calculation used |
outputs | array | {name, title, value, formatString?} per output, in definition order. A cell range may also carry columnFormats, hasHeaderRow and truncated |
result | object | Only with flatten=true: output name to value |
metadata | object | executionTime, totalTime, timestamp, version, optionally cached, exportUrl; more fields may appear |
Reading outputs by name:
const results = Object.fromEntries(data.outputs.map((o) => [o.name, o.value]));
results = {o["name"]: o["value"] for o in data["outputs"]}A failed call has a different shape: error, message and, for input problems, details. See the Error reference.
FAQ
What does the API return?
A JSON object with service, inputs, outputs and metadata. The results are in outputs, a list of entries with name, title and value.
How do I get one result by its name?
Find the entry in outputs whose name matches, or add flatten=true to the address and read result.<name>.
What does flatten=true do?
It adds result to the answer: one object with the output names as keys and the values. The outputs list is still there.
Why is my percentage 0.05 and not 5%?
Values are returned raw, as the cell holds them. formatString carries the cell's number format so you can format the value for display.
How is a cell range returned?
As a table: a list of rows, where each row is a list of cell values. Empty cells are null. How many rows it has, and the fields that describe its columns, are explained under Tables above.
Can I get the answer as CSV?
Yes, on GET add _format=csv. The answer has two lines: the output names and the values.
What is _format=plain for?
It returns one line per output in the form name: value. It is made for Excel's WEBSERVICE function, which returns text.
My output shows "#VALUE!". Is that an error of the API?
No. The call worked and the cell in your workbook holds a formula error for these inputs. Test the same values in the workbook to find the formula.
Why does metadata show cached: true?
An identical call was calculated shortly before and the stored answer was returned. Add nocache=true to force a new calculation; see Caching and performance.
As an agent, which fields of the answer can I rely on?
Rely on service.id, inputs, outputs with name, title, value and optional formatString, result with flatten=true, and the listed metadata fields. Treat other metadata fields as informational.
Are the outputs always in the same order?
Yes, they come in the order of the service definition. Reading by name is still safer, because the owner can reorder outputs.