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

# Concepts

This page explains the core concepts you’ll see throughout the **Documents API documentation**.

<CardGroup>
  <Card title="Quickstart API" href="/getting-started/quickstart-api">
    Create a submission → upload → retrieve results.
  </Card>

  <Card title="Get an access token" href="/getting-started/getting-access-token">
    OAuth2 client credentials across stages and cells.
  </Card>

  <Card title="Receiving results" href="/receiving-results/overview">
    Polling (default) or optional notifications (SQS / webhooks).
  </Card>

  <Card title="View results in the UI" href="/view-results/overview">
    Web UI and Offline iFrame viewer options.
  </Card>
</CardGroup>

***

## End-to-end integration model

The typical lifecycle looks like this:

```mermaid placement="bottom-right" theme={null}
sequenceDiagram
  autonumber
  actor Client as Customer system
  participant API as Documents API
  participant S3 as Upload URL (S3)
  participant UI as Web UI / Offline iFrame (optional)

  Client->>API: POST /v2/submission
  API-->>Client: submission_id + upload_url

  Client->>S3: PUT upload_url (file bytes)
  S3-->>Client: 200 OK

  Client->>API: GET /v2/submission/{submission_id}/fraud
  API-->>Client: status = SUCCESS / FAILED / INVALID_INPUT / SKIPPED

  opt View results
    Client->>UI: /analysis/{submission_id} or postMessage()
    UI-->>Client: Render results
  end
```

<Tip>
  If you’re integrating for the first time, follow the [Quickstart API](/getting-started/quickstart-api). It walks you through the full flow end-to-end.
</Tip>

***

## Key identifiers

### `submission_id`

A server-generated identifier returned when you create a submission. It is the primary identifier used to:

* fetch results (fraud / quality / classification / decision)
* deep link into the Web UI
* delete a submission

### `query_id`

An optional, customer-defined identifier you provide at submission creation time. Use it to correlate results with your internal system (e.g., case ID or document record ID).

<Warning>
  Ensure `query_id` does not contain PII. Use opaque internal IDs (UUIDs) instead of emails, names, phone numbers, etc.
</Warning>

***

## Environments

### Stage

* **Production**: live processing
* **Testing**: used to validate integration behavior before go-live (limited to EU region)

### Cell

A short identifier used in hostnames to indicate the deployment “cell”, such as:

* `eu-1` (no hostname prefix)
* `us-1`, `ca-1`, `ap-2`, `ap-3` (appear as hostname prefixes)

Example:

* EU prod API: `api.documents.resistant.ai`
* US prod API: `api.us-1.documents.resistant.ai`

### AWS region (storage endpoints)

S3 upload/download endpoints use standard AWS region identifiers (e.g., `eu-west-1`, `us-east-1`).

<Tip>
  Always keep your **API base URL**, **token URL**, and **allowlist** aligned to the same stage + cell.
</Tip>

***

## Pipelines and results

When creating a submission, you choose which analysis pipeline to run via `pipeline_configuration`:

* `FRAUD_ONLY`: run fraud pipeline (default)
* `CLASSIFICATION_ONLY`: run classification only
* `QUALITY_ONLY`: run quality only

Results are retrieved from these endpoints (depending on what you enabled/consume):

* Fraud result: `GET /v2/submission/{submission_id}/fraud`
* Quality result: `GET /v2/submission/{submission_id}/quality`
* Classification result: `GET /v2/submission/{submission_id}/classification`
* Adaptive Decision result: `GET /v2/submission/{submission_id}/decision`
* PDF report: `GET /v2/submission/{submission_id}/report`

***

## Result status model (terminal states)

Result endpoints return a response with a `status` field. Treat these as **terminal states**:

* `SUCCESS`: results are available
* `FAILED`: processing failed during backend analysis
* `INVALID_INPUT`: document could not be processed (e.g., unsupported or malformed)
* `SKIPPED`: the step did not run (commonly due to pipeline configuration)

<Tip>
  Your integration should stop polling once a terminal status is returned and handle the outcome in your workflow (e.g., manual review on `FAILED`/`INVALID_INPUT`).
</Tip>

<Note>
  Adaptive Decision responses may also include `INVALID_PIPELINE_CONFIG` when a required pipeline input is missing.
</Note>

***

## Receiving results: polling vs notifications

### Polling (default)

Most customers retrieve results by polling the relevant endpoint(s) until a terminal status is returned.

Recommended approach:

* exponential backoff
* cap interval at **45 seconds**
* stop after **15 minutes** (hard analysis timeout)

### Optional notifications

Instead of polling, some customers use:

* **Amazon SQS event notifications** (optional add-on)
* **Webhooks via Svix** (optional add-on)

These options notify your system when processing completes and include a pointer (URL/endpoint) to fetch full results.

***

## Viewing results

### Web UI

A hosted browser-based UI used by investigators/analysts to review results, indicators, and document previews.

**Deep link format**

```text theme={null}
https://<tenant>-<org>.documents.resistant.ai/analysis/<submission_id>
```

See: [View results in the UI](/view-results/overview)

### Offline iFrame viewer

A self-hosted viewer that renders results in your environment. You provide:

* the original file bytes (`ArrayBuffer`)
* result payloads via `postMessage()`:
  * `fraud` (required)
  * `decision` (optional)
  * `classification` (optional)

<Warning>
  The Offline iFrame viewer requires provisioning and is enabled by agreement. Do not treat it as a public, self-serve asset.
</Warning>

See: [View results in the UI](/view-results/overview)

***

## Optional features that affect the model

### Submission characteristics

Submission characteristics are optional metadata attached to a submission (device, identity, transaction context, etc.).

Important behavior:

* if you set `enable_submission_characteristics=true` at submission creation time, then providing characteristics becomes **required** for that submission to be analyzed.

### Payload encryption

Optional end-to-end encryption of uploaded file bytes (JWE) for additional protection beyond TLS. It changes the upload payload format but does not change the submission/result flow.

### Delete submission

You can delete a submission via:

* `DELETE /v2/submission/{submission_id}`

Use this to delete data earlier than your configured retention period.

***

## Common misunderstandings

<AccordionGroup>
  <Accordion title="Do I upload the file to the Documents API directly?">
    No. You upload the file bytes to the presigned `upload_url`returned from “Create submission” using HTTP `PUT `with `Content-Type: application/octet-stream`
  </Accordion>

  <Accordion title="Should I base64-encode the file before upload?">
    No. Upload the original file bytes.
  </Accordion>

  <Accordion title="Can I request a new access token for every API request?">
    Don’t. Reuse the token until it expires (`expires_in`) to avoid unnecessary token endpoint load.
  </Accordion>

  <Accordion title="Do token URLs differ by stage/cell?">
    Yes. Token URLs are environment-specific. Always use the token URL provided for your stage + cell.
  </Accordion>
</AccordionGroup>
