# createClassifications

Submit a unified classification request

`POST /api/v2/companies/{companyId}/classifications`

**API:** Avalara Item Classification API
**Tag:** Classifications
**API Version:** 16.0.1-oas3
**Base URL:** https://api-sandbox.classification.avalara.net
**Authentication:** Basic (username + license key) or Bearer token

Source: https://developer.avalara.com/products/managed-and-premium-tariff-code/api/methods/Classifications/createClassifications/

## Description

Accepts a **JSON** body (`application/json`) in three shapes:
1. Single object with `item`.
2. Single object with `items[]` sharing classification config.
3. Top-level JSON array of independent requests.

**Document upload (`multipart/form-data`).** The same URL also accepts a document upload:
submit a PDF and/or image(s) and the service reads them into classification object(s) before
classifying (it does not require a structured `item`). Routing is by `Content-Type`
(`application/json` → JSON shapes above; `multipart/form-data` → document upload). Uploaded
files are validated (type, size, page count, readability, encryption, image quality) and one
classification result is returned per distinct product extracted from the document(s).
Extraction that yields no products returns `422` (`EXTRACTION_EMPTY`); if the extraction
service is unreachable the response is `503`, and an extraction error is `502`.

**Success responses** (`201 Created`, `207 Multi-Status`) are always `{ "items": [...] }`.

**HTTP-level errors** (`403`, `413`, `422`, `429`, `503`, `500`, and `401` from the gateway) return
the **AvaTax error envelope** (`AvaTaxError`) — `{ "error": { "code", "target", "details"[] } }` —
the same structural shape used for OAuth/gateway failures. Only **nested** rejections inside
a `207` item / per-COD result still use the small `{ "code", "message" }` object (`Error`).

## Parameters

| Name | Type | In | Required | Description |
|---|---|---|---|---|
| `undefined` |  |  | No |  |
| `undefined` |  |  | No |  |
| `undefined` |  |  | No |  |
| `undefined` |  |  | No |  |
| `undefined` |  |  | No |  |
| `undefined` |  |  | No |  |
| `undefined` |  |  | No |  |

## Request Body

**Content-Type:** `application/json`

**Content-Type:** `multipart/form-data`
**Schema:** `DocumentUploadRequest`

`multipart/form-data` body for the document-upload variant of this endpoint. Submit a PDF
and/or image(s); the service reads them into classification object(s) and classifies them.
At least one of `pdf`, `images`, `text`, `imageUrl`, or `url` must be supplied. The
classification-intent fields (`classificationType`, `classifications`, `countryOfDestination`)
are applied to every product extracted from the document(s). Files are validated for type,
size (≤ 25 MB/file, ≤ 50 MB total, ≤ 10 files), page count (≤ 50), readability, encryption,
and image quality before extraction.

| Property | Type | Required | Description |
|---|---|---|---|
| `pdf` | string | No | A single PDF document to classify. |
| `images` | string[] | No | One or more image files (PNG / JPG / JPEG). Repeat the field to send several. |
| `text` | string | No | Raw product text/description (alternative or supplement to a file). |
| `title` | string | No | Optional product title hint. |
| `imageUrl` | string | No | URL of a product image to read, instead of or in addition to an uploaded file. |
| `url` | string | No | URL of a product page to read. |
| `countryOfExport` | string | No | ISO 3166-1 alpha-2 country-of-export hint. |
| `isExport` | boolean | No | When true, classify using export (Schedule B) codes. |
| `classificationType` | string | No | Classification tier applied to every extracted product. Values: `managed`, `autoPro`, `autoEssentials`. |
| `classifications` | string | No | Comma-separated classification activities applied to every extracted product — e.g.
`hsFull` or `hsFull,compliance`. Allowed: `hsFull`, `hs6`, `export`, `compliance`, `coo`, `premium`. |
| `countryOfDestination` | string | No | Comma-separated ISO 3166-1 alpha-2 destination country codes applied to every extracted
product — e.g. `US` or `US,CA`. Required when `classifications` includes `hsFull`/`hs6`. |

## Responses

| Status | Description | Schema |
|---|---|---|
| 201 | All items accepted and all classifications produced.

## Index-based correlation

`items[i]` in the response corresponds positionally to:
- `items[i]` in the request body when the caller used the `items[]` shape, or
- the i-th element of the top-level JSON array when the caller used the array shape, or
- the single response element `items[0]` when the caller used the single `item` shape.

## Partial-success caveat inside 201

Even on `201`, individual classifications can carry
`status: cannotBeClassified` (auto path with no Indix prediction)
or `status: pending` (managed path). Per-COD rejections that
warrant HTTP escalation surface as **207 Multi-Status** instead. | `ClassificationResponse` |
| 207 | Multi-status — some items or per-COD classifications were rejected.

## Index-based correlation

`items[i]` in the response corresponds positionally to `items[i]`
in the request body (or the i-th element when an array body was
sent). Per-item rejections appear under `items[i].error`;
per-COD rejections inside an otherwise-accepted item appear
under `items[i].classifications[j].error`. | `ClassificationResponse` |
| 401 | Gateway authentication failure - the request was rejected by
the upstream authentication layer BEFORE the unify controller
ran. Body uses `AvaTaxError` (not the small nested `Error` used
only inside **`207`** payloads). All other HTTP failures on this
POST also use `AvaTaxError` — branch on **HTTP status** and
**`error.code`** / **`details[].number`**, not on a second top-level
`{ "code", "message" }` shape.

Sub-cases (distinguished by `error.code` /
`error.details[0].number`):
- `AuthorizationException` (31) - token valid but caller is
  not authorised for this account / operation.
- `AuthenticationIncomplete` (34) - missing `Authorization`
  header.
- `BearerTokenInvalid` (37) - token unrecognised or expired. | `AvaTaxError` |
| 403 | Authenticated caller is not entitled to the requested `classificationType` or modifier
(e.g. an ungranted `classificationType`, the `mtccPlus` modifier, or `compliance`/
`enrichContent`). Per the HTTP status guideline (§4.7.3) an authenticated caller lacking
entitlement/permission receives **403 Forbidden**.
Uses the AvaTax envelope (`error.code`: `EntitlementRequired` number **3015**, or
`MtccPlusNotProvisioned` number **3011** when the `mtccPlus` modifier is not provisioned). | `AvaTaxError` |
| 413 | Request exceeds a per-request size cap. Either `items[]` > configured max
(`unify.max.items.per.request`), `countryOfDestination[]` > configured max
(`unify.max.countries.of.destination`), or auto bulk over its own cap.
Body is `PayloadTooLarge` (number **3016**) in the AvaTax envelope. | `AvaTaxError` |
| 422 | Request validation (`ModelStateInvalid`, number **70**), minimal-field validation,
missing body (`ValueRequiredError`, **5**), or `ErrorCodeException` translated via
`HSClassificationErrors.translateError` — all returned as the AvaTax envelope.
Validator rules surface as `error.code: ModelStateInvalid` with each failed rule in
`details[]` using the unify rule code in `details[].code`. | `AvaTaxError` |
| 429 |  |  |
| 500 | Unhandled server error (`UnhandledException`). AvaTax envelope. | `AvaTaxError` |
| 502 | Document upload only: the document-extraction service returned an error or an unusable
response. Returned as the AvaTax error envelope. | `AvaTaxError` |
| 503 | Upstream AvaTax / HTTP dependency did not respond in time (`RetryRequest`, number **3008**),
or — for a document upload — the document-extraction service was unreachable.
Returned as AvaTax envelope; `severity` is typically `Warning`. | `AvaTaxError` |

### 201 Response: `ClassificationResponse`

| Property | Type | Required | Description |
|---|---|---|---|
| `items` | ItemResult[] | No |  |

## Example Request

```bash
curl -X POST "https://api-sandbox.classification.avalara.net/api/v2/companies/{companyId}/classifications" \
  -H "Authorization: Basic <credentials>" \
  -H "Accept: application/json"
```