> ## Documentation Index
> Fetch the complete documentation index at: https://zerodrift.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Start Import

> Start rule extraction after uploading a policy file via presigned URL

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](/api-reference/custom-policies/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](/api-reference/custom-policies/get-import-details) until the status
transitions to `pending_review`, `no_rules_found`, or `failed` — identical to the inline
[Import Policy](/api-reference/custom-policies/import-policy) flow.

## Request Body

<ParamField body="import_id" type="string" required>
  The `import_id` returned by [Get Import Presigned URL](/api-reference/custom-policies/import-presigned-url).
</ParamField>

<ParamField body="filename" type="string">
  Optional filename to record on the import (overrides the value from the presigned step).
</ParamField>

## Response

<ResponseField name="import_id" type="string">
  Unique identifier for the import. Use it to poll for status or activate rules.
</ResponseField>

<ResponseField name="status" type="string">
  `processing` once extraction has started, or `scan_pending` if the malware scan is still
  running (retry shortly).
</ResponseField>

<ResponseField name="message" type="string">
  Human-readable message with next steps.
</ResponseField>

<ResponseExample>
  ```json 202 Import Accepted theme={null}
  {
    "import_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "processing",
    "message": "Import accepted. Poll GET /api/policies/import/{import_id} for results."
  }
  ```

  ```json 202 Scan Pending theme={null}
  {
    "import_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "scan_pending",
    "message": "File is still being scanned. Retry POST /api/policies/import/start shortly."
  }
  ```

  ```json 404 Not Found theme={null}
  {
    "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"
  }
  ```
</ResponseExample>

## 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                                        |

<Note>
  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.
</Note>

## Example

<CodeGroup>
  ```bash cURL theme={null}
  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"
    }'
  ```

  ```python Python theme={null}
  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)}")
  ```

  ```javascript JavaScript theme={null}
  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);
  })();
  ```
</CodeGroup>
