# Goods conditions and inspected quantities

A condition belongs to a specific physical quantity. The same article and lot may contain new, used, blocked and uninspected quantities simultaneously. Article master data alone does not certify a sale release.

Keep three properties separate:

- `code` and `name` identify your condition, for example `used_inspected` and “Used, inspected”.
- `quality_grade` is an optional grade from your own catalog. Meykt does not guess Amazon, eBay or other marketplace grades.
- `disposition` controls use: `quarantine` awaits inspection, `blocked` is unavailable, and `released` permits order allocation.

Catalog codes, provider codes and non-null quality grades use lowercase letters, digits, `_` or `-`, starting with a letter (maximum64 characters). Send `quality_grade: null` when no grade is assigned. Display names and external condition codes retain their documented text and case; external codes are never silently normalized into another marketplace meaning.

Existing unclassified legacy stock retains its previous operational availability. It is **not** thereby certified as new or inspected. `certified_available` excludes it. Publishing legacy stock requires a deliberate policy that includes it.

## Permissions and responsibility

| Operation | Required scopes |
| --- | --- |
| Read conditions and code mappings | `conditions:read`, `inventory:read` |
| Create a condition or mapping version | `conditions:write` |
| Select goods in your operator custody | `inventory:operator_read`, `conditions:read` |
| Reclassify an actual quantity | `inventory:classify` |
| Read an original receipt | `conditions:read`, `inventory:read` |

Previews additionally require the corresponding read scopes; the endpoint reference lists the complete combination. The key's current creator must retain the appropriate warehouse permission. A scope does not replace that permission.

The owner view at `/v1/inventory/positions` includes owned goods at currently authorized fulfillment partners. The separate operator view at `/v1/inventory/operator-positions` covers actual custody in the API organization's warehouses, including currently released customer goods. Existing keys with only `inventory:read` gain no additional partner access.

Only the actual warehouse operator can classify its goods. A fulfillment customer cannot release goods held by another operator using its own key. Relationships and article releases are checked again when the action executes.

## Condition versions and external codes

`GET /v1/conditions` returns the complete own catalog and mappings, within the documented limit of 1,000 entries each. Historical versions remain available. Creating a new version never changes existing quantities.

Create a condition with `POST /v1/conditions/commands`:

```json
{
  "idempotency_key": "c1000000-0000-4000-8000-000000000001",
  "operation": {
    "kind": "define",
    "code": "used_inspected",
    "name": "Used, inspected",
    "quality_grade": "a",
    "disposition": "released",
    "expected_catalog_version": 0,
    "reason": "Defined inspection criteria for used goods"
  }
}
```

`expected_catalog_version: 0` means the code has no existing version. To create a subsequent version, use the last observed version of that code. The response includes its new `condition_id` and `catalog_version`.

Use the same route with `kind: "map"` to map an external code. Supply `provider`, `market`, `category`, `external_code`, the exact `condition_id`, `expected_mapping_version` and `reason`. Provider, market, category and external code jointly identify the mapping. There is no implicit global mapping or fallback to “new” for unknown codes. `expected_mapping_version: 0` creates the first mapping; every subsequent change creates another version.

`POST /v1/conditions/commands/preview` checks the same operation without saving it. `saved: false` is not a committed receipt. Identifiers generated by a preview do not identify existing conditions and must not be used for subsequent commands.

## Select goods and release a partial quantity

1. Read `GET /v1/inventory/operator-positions`, optionally filtering by `warehouse_id`, `search`, `cursor` and `limit` (maximum 250). Use `position_id` to refresh a known position directly. Search supports `%` for any number of characters and `_` for one character.
2. Retain the selected position's `id` and `revision`. `owner_ref`, `article_ref` and `lot_ref` are neutral, stable references. `batch` and `received_at` distinguish real receipts of the same article at the same location. Foreign organization identifiers are not exposed.
3. Deliberately select an own condition version from `/v1/conditions`.
4. Call `POST /v1/inventory/classifications/preview` with the intended command.
5. Submit the reviewed command to `POST /v1/inventory/classifications`.

```json
{
  "idempotency_key": "c1000000-0000-4000-8000-000000000002",
  "operation": {
    "kind": "reclassify",
    "position_id": "c1000000-0000-4000-8000-000000000010",
    "expected_revision": 3,
    "condition_id": "c1000000-0000-4000-8000-000000000020",
    "quantity": "2.000001",
    "reason": "This exact partial quantity has been inspected"
  }
}
```

Quantities are exact decimal strings with at most six decimal places. JSON numbers and exponential notation are rejected. The maximum quantity per classification is `999999999`.

Only the selected quantity receives the new condition. A partial classification leaves the remainder separate; the total physical quantity does not change. The receipt contains `source_position_id`, `target_position_id` and their revisions. Reserved or exclusively held positions cannot be reclassified, including an already bound target position. Resolve the corresponding order, inbound or return allocation through its designated workflow first.

A stale revision is rejected. Read the current state and review a **new business decision**. Never create a fresh key merely to bypass an uncertain result of the original command.

The operator list is a live work selection, not a frozen synchronization snapshot. Positions can change between pages. For complete inventory synchronization, use the snapshots and change stream described in [Inventory](inventory).

## Uncertain responses and receipts

Read `GET /v1/conditions/commands/{idempotencyKey}` or repeat exactly the original payload with the same key. The permanent receipt is bound to that API connection and input. Another connection or changed arguments cannot adopt it.

`null` means no receipt was found, not that the command failed. A receipt records the original booking and is not a current inventory snapshot. While the outcome is uncertain, wait or retry only the original command. Do not repeat a physical inspection or movement merely to obtain a response.

Classification has no automatic undo operation. A later correction is another explained classification of actual, unbound goods. The original receipt remains intact.

## Test keys and physical receiving

Test keys return empty condition and operator lists. They cannot create real catalog versions, mappings or classifications. Use isolated simulator fixtures for complete write tests.

These endpoints do not set arbitrary stock balances. Receive actual goods through [Inbounds](inbounds) and [Returns](returns). Physical acceptance creates stock; an announcement or new condition version does not.
