curl --request POST \
--url https://api.example.com/api/decisions/{workspace}/spreadsheet/parse \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form file=@example-file \
--form hit_policy=first \
--form 'sheet=<string>'import requests
url = "https://api.example.com/api/decisions/{workspace}/spreadsheet/parse"
files = { "file": ("example-file", open("example-file", "rb")) }
payload = {
"hit_policy": "first",
"sheet": "<string>"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('file', '<string>');
form.append('hit_policy', 'first');
form.append('sheet', '<string>');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.example.com/api/decisions/{workspace}/spreadsheet/parse', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/decisions/{workspace}/spreadsheet/parse",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"hit_policy\"\r\n\r\nfirst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"sheet\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/decisions/{workspace}/spreadsheet/parse"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"hit_policy\"\r\n\r\nfirst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"sheet\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/decisions/{workspace}/spreadsheet/parse")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"hit_policy\"\r\n\r\nfirst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"sheet\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/decisions/{workspace}/spreadsheet/parse")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"hit_policy\"\r\n\r\nfirst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"sheet\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"sheet": "<string>",
"rows_read": 123,
"spec": {},
"columns": [
{
"header": "<string>",
"side": "<string>",
"field": "<string>",
"type": "<string>",
"type_declared": false,
"note": "<string>"
}
],
"problems": [
{
"row": 123,
"detail": "<string>",
"column": "<string>"
}
],
"shadowed": [
{
"row": 123,
"shadowed_by": 123,
"detail": "<string>"
}
],
"content": "<string>",
"compile_error": "<string>"
}{
"error": "<string>",
"code": 500
}{
"error": "<string>",
"code": 500
}{
"error": "<string>",
"code": 500
}{
"error": "<string>",
"code": 500
}{
"error": "<string>",
"code": 500
}Read a rule spreadsheet without storing anything
Read a workbook and report what it says. Nothing is stored.
This step exists because column types are inferred. A column of ages read as text compiles, validates, and then never matches, so the reading is shown back — every column, including the ones that were skipped — while correcting it is still an edit to a spreadsheet rather than a version someone has to reject.
The response also carries the compiled graph and any rows that can never fire, so the whole picture is available before the first write.
Required roles: author or workspace_admin
curl --request POST \
--url https://api.example.com/api/decisions/{workspace}/spreadsheet/parse \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form file=@example-file \
--form hit_policy=first \
--form 'sheet=<string>'import requests
url = "https://api.example.com/api/decisions/{workspace}/spreadsheet/parse"
files = { "file": ("example-file", open("example-file", "rb")) }
payload = {
"hit_policy": "first",
"sheet": "<string>"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('file', '<string>');
form.append('hit_policy', 'first');
form.append('sheet', '<string>');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.example.com/api/decisions/{workspace}/spreadsheet/parse', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/decisions/{workspace}/spreadsheet/parse",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"hit_policy\"\r\n\r\nfirst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"sheet\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/decisions/{workspace}/spreadsheet/parse"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"hit_policy\"\r\n\r\nfirst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"sheet\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/decisions/{workspace}/spreadsheet/parse")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"hit_policy\"\r\n\r\nfirst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"sheet\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/decisions/{workspace}/spreadsheet/parse")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"hit_policy\"\r\n\r\nfirst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"sheet\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"sheet": "<string>",
"rows_read": 123,
"spec": {},
"columns": [
{
"header": "<string>",
"side": "<string>",
"field": "<string>",
"type": "<string>",
"type_declared": false,
"note": "<string>"
}
],
"problems": [
{
"row": 123,
"detail": "<string>",
"column": "<string>"
}
],
"shadowed": [
{
"row": 123,
"shadowed_by": 123,
"detail": "<string>"
}
],
"content": "<string>",
"compile_error": "<string>"
}{
"error": "<string>",
"code": 500
}{
"error": "<string>",
"code": 500
}{
"error": "<string>",
"code": 500
}{
"error": "<string>",
"code": 500
}{
"error": "<string>",
"code": 500
}Authorizations
The access token received from the authorization server in the OAuth 2.0 flow.
Path Parameters
Workspace slug.
64^[a-z0-9][a-z0-9-]{0,63}$Body
Response
Successful Response
The reading of an uploaded workbook. Nothing has been stored.
The sheet that was read.
Non-blank rows below the header.
The rule table as columns and rows. Submit this back to /versions/from-spec after any correction, or re-upload the corrected workbook.
One entry per spreadsheet column, including the ones that were not read — a header typo is never silent.
Show child attributes
Show child attributes
Cells that could not be translated. Empty means a clean read.
Show child attributes
Show child attributes
Rows an earlier row already covers, so they can never fire under the first hit policy.
Show child attributes
Show child attributes
The compiled JDM, when the spec compiled. Null when it did not — see problems.
Why the rows could not be compiled, if they could not.
Was this page helpful?

