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

# Get Validation Results

> Retrieve results of an async validation job

Retrieve results of an asynchronous validation job. Poll this endpoint until status is `done` or `failed`.

## Request Body

<ParamField body="job_id" type="string" required>
  Job ID to retrieve results for
</ParamField>

## Response

<ResponseField name="job_id" type="string">
  Unique identifier for the validation job
</ResponseField>

<ResponseField name="status" type="string">
  Job status: `started`, `in_progress`, `done`, or `failed`
</ResponseField>

<ResponseField name="started" type="string">
  ISO 8601 UTC timestamp when the job was created. Present from the initial `started` status onward.
</ResponseField>

<ResponseField name="timestamp" type="string">
  ISO 8601 UTC timestamp of the current status snapshot.
</ResponseField>

<ResponseField name="overall_status" type="string">
  Overall compliance assessment (when done): `approved`, `needs_changes`, or `do not send`. Note: the `do not send` value contains spaces — this matches the API response exactly.
</ResponseField>

<ResponseField name="summary" type="object">
  Summary of violations by severity

  <Expandable title="summary properties">
    <ResponseField name="critical" type="integer">
      Count of critical severity violations
    </ResponseField>

    <ResponseField name="major" type="integer">
      Count of major severity violations
    </ResponseField>

    <ResponseField name="medium" type="integer">
      Count of medium severity violations
    </ResponseField>

    <ResponseField name="minor" type="integer">
      Count of minor severity violations
    </ResponseField>

    <ResponseField name="document_pages" type="integer">
      Number of pages in the document
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="violating_line_count" type="integer">
  Number of lines with at least one compliance violation. Absent for older jobs or when only grouped fixes exist.
</ResponseField>

<ResponseField name="compliant_line_count" type="integer">
  Number of lines with no violations. Absent for older jobs or when only grouped fixes exist.
</ResponseField>

<ResponseField name="total_line_count" type="integer">
  Total number of lines in the document. Absent for older jobs or when only grouped fixes exist.
</ResponseField>

<ResponseField name="revalidation_recommended" type="boolean">
  True when more than one fix is found, suggesting a re-scan after applying all fixes.
</ResponseField>

<ResponseField name="violations_by_line" type="array">
  One entry per violating line, with all rules violated and the best fix. Absent for older jobs or when only grouped fixes exist. Present but empty for fully compliant documents.

  <Expandable title="LineViolation properties">
    <ResponseField name="line_number" type="integer">
      1-indexed line number in the document
    </ResponseField>

    <ResponseField name="line_text" type="string">
      The text content of the violating line (trimmed)
    </ResponseField>

    <ResponseField name="char_from" type="integer">
      Character offset of the best fix's original text start
    </ResponseField>

    <ResponseField name="char_to" type="integer">
      Character offset of the best fix's original text end
    </ResponseField>

    <ResponseField name="page" type="integer">
      Page number where the violation appears
    </ResponseField>

    <ResponseField name="rule_count" type="integer">
      Number of distinct rules violated on this line
    </ResponseField>

    <ResponseField name="rules_violated" type="array">
      All rules violated on this line, sorted by severity then confidence

      <Expandable title="rule properties">
        <ResponseField name="rule_name" type="string">
          Name of the compliance rule
        </ResponseField>

        <ResponseField name="rule_ref" type="string">
          Regulatory citation (e.g., `FINRA 2210(d)(1)(B)`)
        </ResponseField>

        <ResponseField name="severity" type="string">
          Severity level: `Critical`, `Major`, `Medium`, or `Minor`
        </ResponseField>

        <ResponseField name="confidence" type="number">
          Confidence score (0-1)
        </ResponseField>

        <ResponseField name="action" type="string">
          Fix action: `replace`, `insert_after`, `remove`, or `warning`
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="best_fix" type="object">
      The recommended fix for this line (from the highest-severity, highest-confidence rule)

      <Expandable title="best_fix properties">
        <ResponseField name="severity" type="string">
          Severity level of the violation
        </ResponseField>

        <ResponseField name="rule_name" type="string">
          Name of the compliance rule
        </ResponseField>

        <ResponseField name="rule_ref" type="string">
          Regulatory citation
        </ResponseField>

        <ResponseField name="action" type="string">
          Fix action: `replace`, `insert_after`, `remove`, or `warning`
        </ResponseField>

        <ResponseField name="suggested_text" type="string | null">
          The replacement text (null when action is `remove` or `warning`)
        </ResponseField>

        <ResponseField name="human_action" type="string">
          Human-readable description of the fix action
        </ResponseField>

        <ResponseField name="confidence" type="number">
          Confidence score (0-1)
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="fixes" type="array">
  Individual fix entries (rule-centric, one per violation per quote)
</ResponseField>

<ResponseField name="fixes_group" type="object">
  Grouped fixes for rules that aggregate across pages
</ResponseField>

<ResponseField name="metadata" type="object">
  Document metadata used for scenario matching
</ResponseField>

<ResponseField name="error" type="string">
  Error message (when status is `failed`)
</ResponseField>

## Job Status Values

| Status        | Description                           |
| ------------- | ------------------------------------- |
| `started`     | Job created and queued for processing |
| `in_progress` | Validation in progress                |
| `done`        | Validation completed successfully     |
| `failed`      | Validation failed with error          |

## Overall Status Values

| Status          | Description                                                    |
| --------------- | -------------------------------------------------------------- |
| `approved`      | Document passes compliance checks                              |
| `needs_changes` | Document has violations that should be addressed               |
| `do not send`   | Document has critical violations and should not be distributed |

<ResponseExample>
  ```json Processing theme={null}
  {
    "job_id": "abc123def456",
    "status": "in_progress",
    "started": "2026-01-08T10:30:00Z",
    "timestamp": "2026-01-08T10:30:15Z"
  }
  ```

  ```json Completed theme={null}
  {
    "job_id": "abc123def456",
    "status": "done",
    "started": "2026-01-08T10:30:00Z",
    "timestamp": "2026-01-08T10:30:45Z",
    "overall_status": "needs_changes",
    "summary": {
      "critical": 0,
      "major": 2,
      "medium": 0,
      "minor": 1,
      "document_pages": 1
    },
    "violating_line_count": 2,
    "compliant_line_count": 3,
    "total_line_count": 5,
    "revalidation_recommended": true,
    "violations_by_line": [
      {
        "line_number": 2,
        "line_text": "Our fund guarantees 18% returns with no downside risk.",
        "char_from": 45,
        "char_to": 98,
        "page": 1,
        "rule_count": 1,
        "rules_violated": [
          {
            "rule_name": "Prohibited Promissory Language (Keywords)",
            "rule_ref": "FINRA 2210(d)(1)(B)",
            "severity": "Critical",
            "confidence": 0.92,
            "action": "replace"
          }
        ],
        "best_fix": {
          "severity": "Critical",
          "rule_name": "Prohibited Promissory Language (Keywords)",
          "rule_ref": "FINRA 2210(d)(1)(B)",
          "action": "replace",
          "suggested_text": "Our fund has historically delivered returns, though past performance does not guarantee future results.",
          "human_action": "Replace promissory language with compliant disclosure",
          "confidence": 0.92
        }
      }
    ],
    "fixes": [],
    "fixes_group": {},
    "metadata": {
      "document_category": "retail_investor_letter"
    }
  }
  ```

  ```json Failed theme={null}
  {
    "job_id": "abc123def456",
    "status": "failed",
    "started": "2026-01-08T10:30:00Z",
    "timestamp": "2026-01-08T10:30:05Z",
    "error": "Failed to parse document: Invalid PDF format"
  }
  ```
</ResponseExample>

## Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://{api-url}/api/validate_stream_result/" \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"job_id": "abc123def456"}'
  ```

  ```python Python theme={null}
  import requests
  import time

  API_KEY = "YOUR_API_KEY"
  API_BASE = "https://{api-url}"

  def get_results(job_id):
      while True:
          response = requests.post(
              f"{API_BASE}/api/validate_stream_result/",
              headers={
                  "x-api-key": API_KEY,
                  "Content-Type": "application/json"
              },
              json={"job_id": job_id}
          )

          result = response.json()

          if result["status"] in ["done", "failed"]:
              return result

          time.sleep(2)

  results = get_results("abc123def456")
  print(results)
  ```

  ```javascript JavaScript theme={null}
  const axios = require('axios');

  const API_KEY = 'YOUR_API_KEY';
  const API_BASE = 'https://{api-url}';

  async function getResults(jobId) {
    while (true) {
      const response = await axios.post(
        `${API_BASE}/api/validate_stream_result/`,
        { job_id: jobId },
        {
          headers: {
            'x-api-key': API_KEY,
            'Content-Type': 'application/json'
          }
        }
      );

      if (['done', 'failed'].includes(response.data.status)) {
        return response.data;
      }

      await new Promise(resolve => setTimeout(resolve, 2000));
    }
  }

  const results = await getResults('abc123def456');
  console.log(results);
  ```
</CodeGroup>
