curl --request POST \
--url https://api-dev.narrative.io/v1/nql/execute \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"nql": "INSERT INTO \"company_data\".\"1\" (\"id\") VALUES (1)"
}
'import requests
url = "https://api-dev.narrative.io/v1/nql/execute"
payload = { "nql": "INSERT INTO \"company_data\".\"1\" (\"id\") VALUES (1)" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({nql: 'INSERT INTO "company_data"."1" ("id") VALUES (1)'})
};
fetch('https://api-dev.narrative.io/v1/nql/execute', 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-dev.narrative.io/v1/nql/execute",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'nql' => 'INSERT INTO "company_data"."1" ("id") VALUES (1)'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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-dev.narrative.io/v1/nql/execute"
payload := strings.NewReader("{\n \"nql\": \"INSERT INTO \\\"company_data\\\".\\\"1\\\" (\\\"id\\\") VALUES (1)\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
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-dev.narrative.io/v1/nql/execute")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"nql\": \"INSERT INTO \\\"company_data\\\".\\\"1\\\" (\\\"id\\\") VALUES (1)\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-dev.narrative.io/v1/nql/execute")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"nql\": \"INSERT INTO \\\"company_data\\\".\\\"1\\\" (\\\"id\\\") VALUES (1)\"\n}"
response = http.request(request)
puts response.read_body{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "my-etl-workflow",
"specification": "document:\n dsl: '1.0.0'\n namespace: test\n name: test-workflow\n version: '1.0.0'\ndo:\n - createView:\n call: CreateMaterializedViewIfNotExists\n with:\n nql: \"CREATE MATERIALIZED VIEW workflow_output AS SELECT track_id FROM company_data.workflow_input\"\n - refreshView:\n call: RefreshMaterializedView\n with:\n datasetName: workflow_output\n - insertData:\n call: ExecuteDml\n with:\n nql: \"INSERT INTO company_data.workflow_input (track_id) VALUES ('test')\"\n",
"data_plane_id": "d1e2f3a4-b5c6-7890-abcd-ef1234567890",
"company_id": 100,
"created_at": "2025-01-15T10:30:00Z",
"created_by": 20,
"updated_at": "2025-01-15T10:30:00Z",
"status": "active",
"tags": [
"<string>"
],
"run_id": "b7e3f1a2-4c5d-6e7f-8a9b-0c1d2e3f4a5b",
"archived_at": null
}{
"type": null,
"title": "Failed to Parse Query",
"status": 400,
"detail": "Invalid query format.",
"instance": "/nql/validate",
"log_id": "c06fea02-0950-45c6-aaff-07ab07c0d04c",
"debug": null
}{
"type": null,
"title": "Table Already Exists",
"status": 403,
"detail": "The table or materialized view name 'test_stats' already exists. Please choose another name.",
"instance": "/v1/nql/execute",
"log_id": "5f1c9b2e-7a44-4d18-9c3f-2b6e0a15d7c4",
"debug": null
}{
"title": "Unsupported Type Error: DECIMAL",
"status": 422,
"detail": "Column 'decimal_value' has type DECIMAL, which is not supported as an output column of a materialized view. CAST the column to a supported type such as DOUBLE, BIGINT, VARCHAR, BOOLEAN, or TIMESTAMP.",
"instance": "/v1/nql/execute",
"log_id": "c904b703-d41e-4372-9276-9f4bdc8ad031",
"debug": {
"column": "decimal_value",
"type_name": "DECIMAL"
}
}Execute an NQL statement
The execute endpoint in the NQL API allows users to execute their NQL queries.
This endpoint processes the query and performs the specified operations
within the specified data plane. The query runs as a workflow, and the
response carries the ID of that workflow run. Follow the run through the workflows
endpoints; GET /nql/{job_id} only serves forecast jobs started by POST /nql/run.
Supported statements: INSERT, UPDATE, DELETE, EXPLAIN, and CREATE MATERIALIZED VIEW.
Set create_as_view to create a view rather than a materialized table; it applies only to
CREATE MATERIALIZED VIEW and is ignored for other statements.
curl --request POST \
--url https://api-dev.narrative.io/v1/nql/execute \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"nql": "INSERT INTO \"company_data\".\"1\" (\"id\") VALUES (1)"
}
'import requests
url = "https://api-dev.narrative.io/v1/nql/execute"
payload = { "nql": "INSERT INTO \"company_data\".\"1\" (\"id\") VALUES (1)" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({nql: 'INSERT INTO "company_data"."1" ("id") VALUES (1)'})
};
fetch('https://api-dev.narrative.io/v1/nql/execute', 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-dev.narrative.io/v1/nql/execute",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'nql' => 'INSERT INTO "company_data"."1" ("id") VALUES (1)'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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-dev.narrative.io/v1/nql/execute"
payload := strings.NewReader("{\n \"nql\": \"INSERT INTO \\\"company_data\\\".\\\"1\\\" (\\\"id\\\") VALUES (1)\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
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-dev.narrative.io/v1/nql/execute")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"nql\": \"INSERT INTO \\\"company_data\\\".\\\"1\\\" (\\\"id\\\") VALUES (1)\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-dev.narrative.io/v1/nql/execute")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"nql\": \"INSERT INTO \\\"company_data\\\".\\\"1\\\" (\\\"id\\\") VALUES (1)\"\n}"
response = http.request(request)
puts response.read_body{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "my-etl-workflow",
"specification": "document:\n dsl: '1.0.0'\n namespace: test\n name: test-workflow\n version: '1.0.0'\ndo:\n - createView:\n call: CreateMaterializedViewIfNotExists\n with:\n nql: \"CREATE MATERIALIZED VIEW workflow_output AS SELECT track_id FROM company_data.workflow_input\"\n - refreshView:\n call: RefreshMaterializedView\n with:\n datasetName: workflow_output\n - insertData:\n call: ExecuteDml\n with:\n nql: \"INSERT INTO company_data.workflow_input (track_id) VALUES ('test')\"\n",
"data_plane_id": "d1e2f3a4-b5c6-7890-abcd-ef1234567890",
"company_id": 100,
"created_at": "2025-01-15T10:30:00Z",
"created_by": 20,
"updated_at": "2025-01-15T10:30:00Z",
"status": "active",
"tags": [
"<string>"
],
"run_id": "b7e3f1a2-4c5d-6e7f-8a9b-0c1d2e3f4a5b",
"archived_at": null
}{
"type": null,
"title": "Failed to Parse Query",
"status": 400,
"detail": "Invalid query format.",
"instance": "/nql/validate",
"log_id": "c06fea02-0950-45c6-aaff-07ab07c0d04c",
"debug": null
}{
"type": null,
"title": "Table Already Exists",
"status": 403,
"detail": "The table or materialized view name 'test_stats' already exists. Please choose another name.",
"instance": "/v1/nql/execute",
"log_id": "5f1c9b2e-7a44-4d18-9c3f-2b6e0a15d7c4",
"debug": null
}{
"title": "Unsupported Type Error: DECIMAL",
"status": 422,
"detail": "Column 'decimal_value' has type DECIMAL, which is not supported as an output column of a materialized view. CAST the column to a supported type such as DOUBLE, BIGINT, VARCHAR, BOOLEAN, or TIMESTAMP.",
"instance": "/v1/nql/execute",
"log_id": "c904b703-d41e-4372-9276-9f4bdc8ad031",
"debug": {
"column": "decimal_value",
"type_name": "DECIMAL"
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
A NQL query.
A dataplane represent where you would run the query. Your query get compiled to the SQL dialect that your data engine understands. If you leave it blank, your query will target Narrative's dataplane on AWS using Apache Spark. We currently support Snowflake and we plan to support other dataplanes in the future. See https://next.narrative.io/products/narrative-anywhere for more details.
The ID of the compute pool to run on. The compute pool must be active, belong to your company, and be associated with the target data plane. If not specified, the default compute pool for the data plane will be used (if one is configured).
"5c8f4a2e-3b1d-4f6a-9c7e-2d8b1a0f5e93"
When true, a CREATE MATERIALIZED VIEW statement creates a view over the query rather than a
materialized table, so reads run the query instead of returning stored rows. Ignored for any other
statement type, and not compatible with MERGE, DELTA, CHUNKING_STRATEGY, or PARTITIONED_BY.
false
Response
The created workflow and the id of the run started for it.
A created workflow whose run was started, so the run ID is always present.
Unique identifier for a workflow.
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
The name of the workflow, extracted from the specification.
"my-etl-workflow"
The workflow specification in YAML format.
"document:\n dsl: '1.0.0'\n namespace: test\n name: test-workflow\n version: '1.0.0'\ndo:\n - createView:\n call: CreateMaterializedViewIfNotExists\n with:\n nql: \"CREATE MATERIALIZED VIEW workflow_output AS SELECT track_id FROM company_data.workflow_input\"\n - refreshView:\n call: RefreshMaterializedView\n with:\n datasetName: workflow_output\n - insertData:\n call: ExecuteDml\n with:\n nql: \"INSERT INTO company_data.workflow_input (track_id) VALUES ('test')\"\n"
The data plane this workflow is associated with.
"d1e2f3a4-b5c6-7890-abcd-ef1234567890"
The company that owns this workflow.
100
ISO-8601 timestamp of when the workflow was created.
"2025-01-15T10:30:00Z"
The ID of the user who created this workflow.
20
ISO-8601 timestamp of when the workflow was last updated.
"2025-01-15T10:30:00Z"
The current status of the workflow.
active, archived "active"
Tags that describe the workflow.
1 - 128Workflow execution run ID.
"b7e3f1a2-4c5d-6e7f-8a9b-0c1d2e3f4a5b"
ISO-8601 timestamp of when the workflow was archived, or null if active.
null
Was this page helpful?

