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

# Document classification

> Identify document type and issuer, standalone or as part of a full fraud analysis.

<Note>
  This guide uses the default EU base URL (`https://api.documents.resistant.ai`).<br />If your tenant is in another cell (e.g., `us-1`, `ca-1`, `ap-2`, `ap-3`), use the corresponding base URL described in [Concepts](/getting-started/concepts).
</Note>

Document classification identifies **what kind of document was submitted** — its `document_type` (e.g. `bank_document`), a more specific `detailed_type` (e.g. `account_statement`), and, where available, the **issuer**.

## Why use classification

* **Know what you received.** Confirm a submission matches what your workflow expects (e.g., a bank statement, not a random PDF) without manual triage.
* **Apply the right checks.** Classification can drive document-specific fraud checks and [Adaptive Decision](/integrate/adaptive-decision) logic downstream.
* **Catch mismatches early.** Run it standalone and act on the result in seconds, before committing to a full fraud analysis.

<Tip>
  Classification tells you **what** a document is — it's not a fraud or authenticity check. Combine it with [fraud analysis](/integrate/core-integration#fraud-analysis) to assess whether the document can be trusted.
</Tip>

***

## How it works

Classification returns:

* `document_type` — a broad category (e.g. `bank_document`, `id_document`, `invoice`)
* `detailed_type` — a subtype within that category (e.g. `account_statement`, `passport`)
* `issuer` / `issuer_parent` — the legal entity (and parent, if applicable) that issued the document, when identifiable

<Note>
  `issuer`, `issuer_parent`, and `variant` aren't populated for every result — it depends on what the classifier can determine for a given document.
</Note>

### Classification score

The top-level `score` field tells you whether classification succeeded:

| Score | Meaning |
| - | - |
| `CLASSIFIED` | A document type was identified. `document_type` / `detailed_type` are populated. |
| `NOT_CLASSIFIED` | The document couldn't be matched to a known type. |
| `DOCUMENT_MISSING` | No document was available to classify (e.g., the file was never uploaded). |

Check `score` first — treat `document_type` and `detailed_type` as supplementary, not as the primary success signal.

***

## `document_type` → `detailed_type` mapping

Every `detailed_type` belongs to exactly one `document_type`, **except `other`**, which exists separately under every `document_type`. On its own, `other` doesn't tell you which category it belongs to — only the pairing does.

<AccordionGroup>
  <Accordion title="id_document">
    `birth_certificate`, `drivers_license`, `health_insurance_card`, `id_card`, `id_certificate`, `passport`, `residence_permit`, `proof_of_address`, `other`
  </Accordion>

  <Accordion title="income_confirmation">
    `earnings_confirmation`, `earnings_statement`, `earnings_summary`, `employment_offer_letter`, `payslip`, `unemployment_certificate`, `other`
  </Accordion>

  <Accordion title="loan_document">
    `client_assessment`, `costs_estimate`, `loan_agreement`, `loan_application`, `loan_closure`, `security_agreement`, `other`
  </Accordion>

  <Accordion title="bank_document">
    `account_confirmation`, `account_statement`, `transaction_history`, `bank_details`, `fees_statement`, `payment_confirmation`, `bank_card`, `bank_cheque`, `other`
  </Accordion>

  <Accordion title="utility_bill">
    `energy`, `water`, `utilities`, `telco`, `mobile_phone`, `municipal_services`, `other`
  </Accordion>

  <Accordion title="company_information">
    `company_detail`, `employer_identification_number`, `financial_report`, `accounting_records`, `company_share_capital_detail`, `incorporation_certificate`, `other`
  </Accordion>

  <Accordion title="government_document">
    `maternity_allowance_claim`, `property_detail`, `postal_document`, `other`
  </Accordion>

  <Accordion title="commercial_document">
    `invoice`, `receipt`, `delivery_note`, `order_confirmation`, `tracking_note`, `transport_order`, `quote`, `payment_request`, `rate_confirmation`, `load_confirmation`, `order`, `other`
  </Accordion>

  <Accordion title="legal_document">
    `rental_agreement`, `court_document`, `employment_contract`, `contract`, `policy`, `education_certificate`, `marriage_certificate`, `death_certificate`, `divorce_certificate`, `apostille`, `legal_notice`, `other`
  </Accordion>

  <Accordion title="insurance_document">
    `insurance_claim`, `insurance_documentation`, `insurance_claim_settlement`, `investigation_report`, `proof_of_insurance`, `other`
  </Accordion>

  <Accordion title="tax_details">
    `tax_form`, `tax_information`, `other`
  </Accordion>

  <Accordion title="vehicle_documentation">
    `vehicle_appraisal`, `vehicle_registration_certificate`, `vehicle_technical_certificate`, `other`
  </Accordion>

  <Accordion title="other_document">
    `medical_report`, `email`, `letter`, `loan_offer`, `credit_card`, `ticket`, `report`, `paper_date`, `screenshot`, `resume`, `other`
  </Accordion>
</AccordionGroup>

<Note>
  `document_type: "document_missing"` and `document_type: "no_classification"` aren't part of the mapping above — they reflect the classification outcome (see **Classification score**), not a document category. `no_classification` pairs with `detailed_type: "missing"`; `document_missing` has no `detailed_type`.
</Note>

See the [API Reference](/api-reference) for the machine-readable enum.

***

## Two ways to consume classification

### Option 1 — Standalone, near real-time

<Info>
  Standalone classification is an add-on and may not be included in your current packaging or contract. Contact your Resistant AI representative to confirm availability and pricing for your tenant.
</Info>

Create a submission with `pipeline_configuration: "CLASSIFICATION_ONLY"`. Only classification runs, so the result is typically available much faster than a full fraud analysis.

**Best for:** deciding whether to run (and pay for) a full fraud analysis — e.g., rejecting an obviously wrong document type right after upload.

```http theme={null}
POST https://api.documents.resistant.ai/v2/submission
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "query_id": "internal-doc-12345",
  "pipeline_configuration": "CLASSIFICATION_ONLY"
}
```

Upload the file bytes as usual (see [Core Integration Mechanics](/integrate/core-integration)), then fetch the result:

```http theme={null}
GET https://api.documents.resistant.ai/v2/submission/{submission_id}/classification
Authorization: Bearer <access_token>
```

<Tip>
  Still implement polling with backoff rather than assuming a fixed response time — see [Polling for results](/receiving-results/polling).
</Tip>

### Option 2 — As part of a full analysis

Create the submission normally (default `pipeline_configuration: "FRAUD_ONLY"`). Classification runs as part of the full pipeline and becomes available on the same timeline as the fraud result — fetch it from the same `/classification` endpoint once processing completes.

**Best for:** integrations that always run a full fraud analysis and want classification as additional context, without an earlier round trip.

```http theme={null}
POST https://api.documents.resistant.ai/v2/submission
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "query_id": "internal-doc-12345",
  "pipeline_configuration": "FRAUD_ONLY"
}
```

```http theme={null}
GET https://api.documents.resistant.ai/v2/submission/{submission_id}/classification
Authorization: Bearer <access_token>
```

<Note>
  The `/classification` endpoint is the same either way — what changes is `pipeline_configuration` at submission time, and how quickly a result becomes available.
</Note>

***

## Example response

```json theme={null}
{
  "status": "SUCCESS",
  "analysis_time": "2024-03-15T10:30:00Z",
  "deployment_version": "3.5.1",
  "query_id": "internal-doc-12345",
  "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "mime_type": "application/pdf",
  "document_classification": {
    "score": "CLASSIFIED",
    "document_type": "bank_document",
    "detailed_type": "account_statement",
    "issuer_parent": {
      "name": "Example Banking Group",
      "country": "GBR"
    },
    "issuer": {
      "name": "Example Bank Ltd",
      "country": "GBR",
      "issuer_id": "07825439",
      "legal_address": {
        "street_address": "1 Example Street, London, EC1A 1BB"
      }
    },
    "variant": null
  }
}
```

| Field | Description |
| - | - |
| `status` | Terminal status of the classification pipeline — see [Concepts](/getting-started/concepts#result-status-model-terminal-states). |
| `document_classification.score` | Whether classification succeeded — see **Classification score** above. |
| `document_classification.document_type` | Broad document category. `null` when not classified. |
| `document_classification.detailed_type` | Subtype within `document_type`. `null` when not classified. |
| `document_classification.issuer` | Issuing legal entity, when identifiable. |
| `document_classification.issuer_parent` | Parent legal entity of the issuer, when applicable. |
| `document_classification.variant` | Free-text qualifier for a specific document version, when available. |

<Note>
  Non-`SUCCESS` statuses (`FAILED`, `INVALID_INPUT`, `SKIPPED`) follow the same shape as other result endpoints and don't include `document_classification`. See [Concepts](/getting-started/concepts) for status meanings.
</Note>

***

## FAQ

<AccordionGroup>
  <Accordion title="Why don't all results include detailed_type or issuer?">
    Classification combines several sources — visual pattern matching, logo detection, textual content analysis, and in some configurations LLM-based content understanding. Not every source resolves every field: a document can be confidently matched to a `document_type` from its visual layout alone, without enough signal to also narrow down a `detailed_type` or issuer.

    A populated `document_type` with a `null` `detailed_type` or `issuer` is expected, not a bug. If a known issuer repeatedly comes back `null`, [contact support](/support/contact-support) with the `submission_id` — that's useful signal for improving coverage.
  </Accordion>

  <Accordion title="Can document_type be populated with a null detailed_type?">
    Yes. When `detailed_type` is populated it always belongs to the returned `document_type`, but it isn't guaranteed to be populated whenever `document_type` is.
  </Accordion>

  <Accordion title="Why do I sometimes see a classification that looks wrong — e.g., a utility bill classified as an invoice?">
    Some categories sit close to each other by design: a utility bill is structurally a type of invoice, and a government confirmation letter can look like an identity document in some jurisdictions. Document semantics also vary globally, so the taxonomy trades off a single market's exact definitions for consistency across customers and regions.

    If a specific confusion matters for your workflow, [let us know](/support/contact-support) — recurring misclassification patterns are useful for prioritizing improvements.
  </Accordion>

  <Accordion title="What should I do with detailed_type: other?">
    Read it as "confident about the category, not the specific subtype." If `other` shows up often for a category you care about, report it — it may mean we're missing a `detailed_type` value your documents need.
  </Accordion>

  <Accordion title="Will I get the same result for the same document every time?">
    Resubmitting an identical file shouldn't routinely produce a different result. If it does, treat that as worth reporting, not expected behavior.
  </Accordion>
</AccordionGroup>

<Tip>
  Spotted an inconsistency, or a document type/issuer your workflow needs that doesn't fit the current taxonomy? [Contact support](/support/contact-support) with example `submission_id`s.
</Tip>

***

## Next steps

<CardGroup>
  <Card title="Core Integration Mechanics" href="/integrate/core-integration">
    Full submission → upload → results flow.
  </Card>

  <Card title="Adaptive Decision" href="/integrate/adaptive-decision">
    Turn classification and fraud results into a tenant-specific decision.
  </Card>

  <Card title="Polling for results" href="/receiving-results/polling">
    Recommended backoff strategy for both consumption options above.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.