Start Import
curl --request POST \
--url https://api.zerodrift.ai/api/policies/import/start \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"import_id": "<string>"
}
'import requests
url = "https://api.zerodrift.ai/api/policies/import/start"
payload = { "import_id": "<string>" }
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({import_id: '<string>'})
};
fetch('https://api.zerodrift.ai/api/policies/import/start', 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.zerodrift.ai/api/policies/import/start",
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([
'import_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$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.zerodrift.ai/api/policies/import/start"
payload := strings.NewReader("{\n \"import_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
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.zerodrift.ai/api/policies/import/start")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"import_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zerodrift.ai/api/policies/import/start")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"import_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"import_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "processing",
"message": "Import accepted. Poll GET /api/policies/import/{import_id} for results."
}
{
"import_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "scan_pending",
"message": "File is still being scanned. Retry POST /api/policies/import/start shortly."
}
{
"error": "No uploaded file found for this import_id",
"import_id": "550e8400-e29b-41d4-a716-446655440000",
"message": "Upload the file with the presigned URL before calling /start"
}
Custom Policies
Start Import
Start rule extraction after uploading a policy file via presigned URL
POST
/
api
/
policies
/
import
/
start
Start Import
curl --request POST \
--url https://api.zerodrift.ai/api/policies/import/start \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"import_id": "<string>"
}
'import requests
url = "https://api.zerodrift.ai/api/policies/import/start"
payload = { "import_id": "<string>" }
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({import_id: '<string>'})
};
fetch('https://api.zerodrift.ai/api/policies/import/start', 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.zerodrift.ai/api/policies/import/start",
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([
'import_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$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.zerodrift.ai/api/policies/import/start"
payload := strings.NewReader("{\n \"import_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
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.zerodrift.ai/api/policies/import/start")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"import_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zerodrift.ai/api/policies/import/start")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"import_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"import_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "processing",
"message": "Import accepted. Poll GET /api/policies/import/{import_id} for results."
}
{
"import_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "scan_pending",
"message": "File is still being scanned. Retry POST /api/policies/import/start shortly."
}
{
"error": "No uploaded file found for this import_id",
"import_id": "550e8400-e29b-41d4-a716-446655440000",
"message": "Upload the file with the presigned URL before calling /start"
}
Step 2 of the large-file custom policy import flow (after the S3 upload). Call this after uploading your file to the
presigned
upload_url from Get Import Presigned URL.
It verifies the uploaded object and enforces the size cap, then — once malware scanning has
completed successfully — starts asynchronous rule extraction and returns status: "processing".
If the scan is still running, it returns status: "scan_pending" immediately instead; retry the
call until extraction starts (see the note below).
Poll Get Import Details until the status
transitions to pending_review, no_rules_found, or failed — identical to the inline
Import Policy flow.
Request Body
string
required
The
import_id returned by Get Import Presigned URL.string
Optional filename to record on the import (overrides the value from the presigned step).
Response
string
Unique identifier for the import. Use it to poll for status or activate rules.
string
processing once extraction has started, or scan_pending if the malware scan is still
running (retry shortly).string
Human-readable message with next steps.
{
"import_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "processing",
"message": "Import accepted. Poll GET /api/policies/import/{import_id} for results."
}
{
"import_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "scan_pending",
"message": "File is still being scanned. Retry POST /api/policies/import/start shortly."
}
{
"error": "No uploaded file found for this import_id",
"import_id": "550e8400-e29b-41d4-a716-446655440000",
"message": "Upload the file with the presigned URL before calling /start"
}
Error Responses
| Status | Description |
|---|---|
| 400 | Missing/invalid import_id, or the uploaded file is empty |
| 403 | Invalid API key, or the import belongs to another customer |
| 404 | No uploaded file found for this import_id (upload step skipped or failed) |
| 409 | Import already started or completed |
| 413 | Uploaded file exceeds the maximum allowed size (1 GB) |
| 422 | File failed malware/content scanning |
If you receive a
202 with status: "scan_pending", the malware scan is still running
(usually a few seconds). Retry this request shortly — rule extraction does not start until the
scan completes successfully.Example
curl -X POST "https://api.zerodrift.ai/api/policies/import/start" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"import_id": "550e8400-e29b-41d4-a716-446655440000"
}'
import requests
import time
API_KEY = "YOUR_API_KEY"
API_BASE = "https://api.zerodrift.ai"
import_id = "550e8400-e29b-41d4-a716-446655440000"
# Start (retry while the malware scan is still pending)
while True:
resp = requests.post(
f"{API_BASE}/api/policies/import/start",
headers={"x-api-key": API_KEY, "Content-Type": "application/json"},
json={"import_id": import_id},
).json()
if resp.get("status") != "scan_pending":
break
time.sleep(3)
# An error payload (e.g. 404) has no "status" — surface it instead of crashing
if "status" not in resp:
raise SystemExit(f"Start failed: {resp.get('error', resp)}")
print(resp["status"])
# Poll for extraction results
while True:
details = requests.get(
f"{API_BASE}/api/policies/import/{import_id}",
headers={"x-api-key": API_KEY},
).json()
if details.get("status") != "processing":
break
time.sleep(3)
print(f"Status: {details.get('status', details)}")
const axios = require('axios');
const API_KEY = 'YOUR_API_KEY';
const API_BASE = 'https://api.zerodrift.ai';
const importId = '550e8400-e29b-41d4-a716-446655440000';
(async () => {
// Start (retry while the malware scan is still pending)
let started;
while (true) {
try {
const res = await axios.post(
`${API_BASE}/api/policies/import/start`,
{ import_id: importId },
{ headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' } }
);
started = res.data;
} catch (err) {
const payload = err.response?.data ?? err.message;
throw new Error(`Start failed: ${typeof payload === 'string' ? payload : JSON.stringify(payload)}`);
}
if (started?.status !== 'scan_pending') break;
await new Promise(r => setTimeout(r, 3000));
}
if (!started?.status) {
throw new Error(`Start failed: ${JSON.stringify(started)}`);
}
console.log(started.status);
})();
⌘I

