Yotam Ater
05/03/2025, 7:15 AMYotam Ater
05/03/2025, 7:15 AMheaders = {
"Content-Type": "application/json",
"Prefer": "respond-async",
}
r = <http://requests.post|requests.post>(
"https://<ACCOUNT_ID>.<http://suitetalk.api.netsuite.com/services/rest/query/v1/suiteql|suitetalk.api.netsuite.com/services/rest/query/v1/suiteql>",
auth=auth,
headers=headers,
data=json.dumps({"q": "SELECT count(*) FROM Transaction"})
)
Response includes:
Location: https://<ACCOUNT_ID>.<http://suitetalk.api.netsuite.com/services/rest/async/v1/job/702|suitetalk.api.netsuite.com/services/rest/async/v1/job/702>
Step 2 – Poll job status
job_loc = r.headers["Location"]
headers = {
"Content-Type": "application/json",
"Prefer": "transient",
}
j = requests.get(job_loc, auth=auth, headers=headers, params={"expandSubResources": "true"})
Response contains:
.../job/702/task/702/result
Step 3 – Fetch result
result_loc = j.json()['task']['items'][0]['links'][0]['href']
headers = {
"Content-Type": "application/json",
"Prefer": "transient",
}
k = requests.get(result_loc, auth=auth, headers=headers)
But this always returns:
<Response [400]>
With:
{
"o:errorDetails": [
{
"detail": "The required request header 'Prefer' is missing or invalid. Use this header with one of the required values: transient.",
"o:errorCode": "INVALID_HEADER"
}
]
}
I’m following this doc:
https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_161251386312.html#subsect_161278579295
Tried many header combos, always same result.your mom
05/15/2025, 11:58 PM(async function runSuiteQL() {
// --- Configuration ---
const suiteQlQuery = "SELECT * FROM account"; // Your SuiteQL query
const suiteQlEndpoint = "/services/rest/query/v1/suiteql"; // Standard SuiteQL endpoint
// Get the base URL (e.g., https://<accountID>.app.netsuite.com)
const baseUrl = window.location.origin;
const fullUrl = baseUrl + suiteQlEndpoint;
console.log(
`%cAttempting to run SuiteQL query:`,
"color: blue; font-weight: bold;",
suiteQlQuery,
);
console.log(`%cEndpoint:`, "color: blue; font-weight: bold;", fullUrl);
try {
// --- Make the Request ---
const response = await fetch(fullUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Prefer: "transient", // This header is required by your NetSuite environment.
},
body: JSON.stringify({
q: suiteQlQuery,
}),
});
// --- Handle the Response ---
if (!response.ok) {
// Try to get more details from the response body if it's an error
let errorDetails = `HTTP error! Status: ${response.status} ${response.statusText}`;
try {
const errorData = await response.json();
errorDetails += `\nDetails: ${JSON.stringify(errorData, null, 2)}`;
} catch (e) {
// If response body is not JSON, just use the text
const errorText = await response.text();
errorDetails += `\nResponse Text: ${errorText}`;
}
throw new Error(errorDetails);
}
const data = await response.json();
// --- Output the Results ---
if (data && data.items) {
console.log("%cQuery successful! ✅", "color: green; font-weight: bold;");
console.log("%cReturned JSON object:", "color: green;");
console.log(data); // Logs the full response object (includes links, count, etc.)
console.log("%cQuery items (records):", "color: green;");
console.table(data.items); // Displays the items in a table for better readability
// To return the items directly for further use in the console:
// return data.items;
} else {
console.warn(
"%cQuery executed, but no items found or unexpected response structure.",
"color: orange;",
);
console.log(data);
}
} catch (error) {
console.error(
"%c❌ Error running SuiteQL query:",
"color: red; font-weight: bold;",
error.message,
);
if (error.stack) {
console.error(error.stack);
}
}
})();