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

# Quickstart

> Create a review, get notified when it completes, and read the report.

Creating a review is fire-and-forget: you get a `review_id` back immediately,
the review processes asynchronously, and Flightline notifies you the moment it
reaches a terminal state. The flow is create, get notified, read the report.

## 1. Create a review

Attach the full case package when you create the review. A single archive is
the recommended shape; individual PDFs/images are also accepted for smaller
submissions.

<Tabs>
  <Tab title="Multipart upload">
    Upload a full case archive directly with `multipart/form-data`:

    ```bash theme={null}
    curl -X POST https://api.flightlinehq.com/v1/reviews \
      -H "Authorization: Bearer fl_live_..." \
      -F "reference_id=LN-2026-0042" \
      -F "review_type=mortgage_v1" \
      -F "documents=@full-case.zip;type=application/zip"
    ```
  </Tab>

  <Tab title="Signed source URLs">
    Reference a full case archive by signed, time-limited URL Flightline will fetch:

    ```bash theme={null}
    curl -X POST https://api.flightlinehq.com/v1/reviews \
      -H "Authorization: Bearer fl_live_..." \
      -H "Content-Type: application/json" \
      -d '{
        "reference_id": "LN-2026-0042",
        "review_type": "mortgage_v1",
        "documents": [
          {"filename": "full-case.zip", "content_type": "application/zip", "url": "https://files.example.com/signed/full-case.zip?sig=..."}
        ]
      }'
    ```
  </Tab>
</Tabs>

The response returns the created review immediately, with `status: "processing"`:

```json theme={null}
{
  "review_id": "9b1f....",
  "status": "processing",
  "reference_id": "LN-2026-0042",
  "label": null,
  "review_type": "mortgage_v1",
  "document_count": 18,
  "report_available": false,
  "sandbox": false,
  "created_at": "2026-05-30T18:00:00Z",
  "updated_at": "2026-05-30T18:00:00Z"
}
```

<Note>
  Accepted case packages: `.zip`, `.tar`, `.tar.gz`, and `.tgz`. Inside the
  package, include PDFs and common image files (`.png`, `.jpg`/`.jpeg`, `.tif`/`.tiff`,
  `.webp`, `.gif`, `.bmp`). RAR/7z archives, nested archives, executables,
  scripts, Office files, spreadsheets, email containers, and password-protected
  or corrupt archives are not accepted.
</Note>

## 2. Get notified when it completes

**Recommended: webhooks.** Register a webhook endpoint once, then handle the
`review.completed` event (plus `review.failed` and `review.amended`). When `review.completed`
arrives, verify the signature and fetch the report. No polling required. See
[Webhooks](/webhooks) for registration and signature verification.

```json theme={null}
{
  "event": "review.completed",
  "review_id": "9b1f....",
  "reference_id": "LN-2026-0042",
  "status": "completed",
  "occurred_at": "2026-05-30T18:09:12Z"
}
```

**Fallback: polling.** If your environment cannot receive webhooks, poll
`GET /reviews/{review_id}` and read `status`, which moves through `queued`,
`processing`, then `completed` or `failed`. Use exponential backoff (for
example 2s, 4s, 8s, capped around 30s) rather than a tight loop. The review is
ready when `report_available` is `true`.

## 3. Read the report

```bash theme={null}
curl https://api.flightlinehq.com/v1/reviews/9b1f.../report \
  -H "Authorization: Bearer fl_live_..."
```

```json theme={null}
{
  "review_id": "9b1f....",
  "status": "completed",
  "outcome": "issues_found",
  "summary": { "total": 2, "critical": 0, "high": 1, "medium": 1, "low": 0, "info": 0 },
  "issues": [
    {
      "code": "APR-003",
      "severity": "high",
      "category": "compliance",
      "title": "APR tolerance exceeded",
      "summary": "The disclosed APR differs from the recalculated APR beyond tolerance."
    }
  ],
  "report_pdf_url": "https://downloads.example.com/report.pdf?signature=...",
  "report_pdf_expires_at": "2026-05-30T18:14:12Z",
  "sandbox": false,
  "generated_at": "2026-05-30T18:09:12Z"
}
```

`report_pdf_url` is a fresh, short-lived (5 minute) download URL for the
current released report PDF; request this endpoint again to get a new one
after it expires or after an amendment.

The report endpoint returns `404` while the review is still processing and
`422` if it failed, so results never leak before the review is finished.

## In your language

Create the review, then let the `review.completed` webhook tell you it is
ready (see [Webhooks](/webhooks) for the handler and signature check):

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.flightlinehq.com/v1/reviews \
    -H "Authorization: Bearer $FLIGHTLINE_API_KEY" -H "Content-Type: application/json" \
    -d '{"reference_id":"LN-2026-0042","review_type":"mortgage_v1",
         "documents":[{"filename":"full-case.zip","content_type":"application/zip",
                       "url":"https://files.example.com/signed/full-case.zip"}]}'
  # Flightline POSTs a review.completed webhook when done; then GET /reviews/{id}/report
  ```

  ```csharp C# theme={null}
  using System.Net.Http.Json;
  using System.Text.Json;

  using var http = new HttpClient();
  http.DefaultRequestHeaders.Authorization =
      new("Bearer", Environment.GetEnvironmentVariable("FLIGHTLINE_API_KEY"));
  const string BASE = "https://api.flightlinehq.com/v1";

  var payload = new {
      reference_id = "LN-2026-0042",
      review_type = "mortgage_v1",
      documents = new[] { new {
          filename = "full-case.zip", content_type = "application/zip",
          url = "https://files.example.com/signed/full-case.zip" } }
  };
  var created = await (await http.PostAsJsonAsync($"{BASE}/reviews", payload))
      .Content.ReadFromJsonAsync<JsonElement>();
  var reviewId = created.GetProperty("review_id").GetString();
  // Handle the review.completed webhook, then GET {BASE}/reviews/{reviewId}/report
  ```

  ```java Java theme={null}
  // java.net.http (Java 17+) + Jackson for JSON
  import com.fasterxml.jackson.databind.ObjectMapper;
  import java.net.URI;
  import java.net.http.*;

  var http = HttpClient.newHttpClient();
  var json = new ObjectMapper();
  String base = "https://api.flightlinehq.com/v1";
  String key = System.getenv("FLIGHTLINE_API_KEY");

  String createBody = """
      {"reference_id":"LN-2026-0042","review_type":"mortgage_v1",
       "documents":[{"filename":"full-case.zip","content_type":"application/zip",
                     "url":"https://files.example.com/signed/full-case.zip"}]}""";
  var created = http.send(HttpRequest.newBuilder(URI.create(base + "/reviews"))
      .header("Authorization", "Bearer " + key)
      .header("Content-Type", "application/json")
      .POST(HttpRequest.BodyPublishers.ofString(createBody)).build(),
      HttpResponse.BodyHandlers.ofString());
  String reviewId = json.readTree(created.body()).get("review_id").asText();
  // Handle the review.completed webhook, then GET base + "/reviews/" + reviewId + "/report"
  ```
</CodeGroup>

<Tip>
  Prefer webhooks over polling in production: you skip the poll loop entirely
  and find out the moment a review finishes.
</Tip>
