# Lista o saldo de um CD, posição por posição e lote por lote

**GET** `/v1/objects/stock`

Só o que tem quantidade. Paginado (`limit` até 200), na ordem do endereço. `units` soma as unidades de todo o filtro, não só da página. Sem `depot_code`, o CD ativo mais antigo.

> **Ação da chave: `stock.list`** Quem cria a chave escolhe as ações que ela abre; sem esta, a rota recusa com `api_key_action_not_granted`.

## Parâmetros da consulta

- `depot_code` (string): O código do CD. Sem ele, o CD ativo mais antigo.
- `limit` (integer ou string): De 1 a 200; 50 por padrão.
- `location` (string): O endereço de uma posição, com ou sem separador (`03-05-11-01` ou `03051101`).
- `offset` (integer ou string)
- `product` (string): O EAN ou o SKU de um item.
- `status` (string): Um ou mais estados separados por vírgula: `available`, `missing`, `unverified`, `damaged`, `quarantine`.

## Devolve

O `data` do envelope `{ ok, data, error, error_code, field, trace_id }`:

- `depot_code` (string, obrigatório)
- `limit` (integer, obrigatório)
- `offset` (integer, obrigatório)
- `stock` (lista de objeto, obrigatório)
  - `description` (string)
  - `ean` (string, ou nulo)
  - `expires_on` (string, ou nulo)
  - `expiry` ("expired" | "expiring" | null): Vencido, vencendo dentro do alerta da empresa, ou nulo.
  - `location_code` (string)
  - `lot_code` (string, ou nulo)
  - `product_id` (uuid)
  - `qty_available` (integer): O que está na posição menos o reservado.
  - `qty_held` (integer): Reservado por pedido.
  - `qty_on_hand` (integer)
  - `sku` (string, ou nulo)
  - `status` (string): `available`, `missing`, `unverified`, `damaged` ou `quarantine`.
  - `updated_at` (data e hora)
- `total` (integer, obrigatório): Quantas linhas o filtro acha, somadas as páginas.
- `units` (integer, obrigatório): Quantas unidades o filtro acha, somadas as páginas.

## Recusas

### HTTP 400 · Pedido mal formado

- [`invalid_limit`](/erros/invalid_limit.md) (HTTP 400): `limit` fora da faixa: de 1 a 200.
- [`invalid_offset`](/erros/invalid_offset.md) (HTTP 400): `offset` inválido: um inteiro de zero para cima.
- [`version_unknown`](/erros/version_unknown.md) (HTTP 400): A `Kernos-Version` pedida não existe. Use uma das versões declaradas no cabeçalho, ou não o mande.

### HTTP 401 · Sem credencial válida

- [`api_key_expired`](/erros/api_key_expired.md) (HTTP 401): A chave venceu. Gire a chave no painel e use a nova.
- [`api_key_wrong_environment`](/erros/api_key_wrong_environment.md) (HTTP 401): A chave é do outro ambiente: `ksk_test_` vai em https://stag.kernos.com.br, `ksk_live_` em https://api.kernos.com.br.
- [`unauthenticated`](/erros/unauthenticated.md) (HTTP 401): Credencial ausente, inválida ou expirada.

### HTTP 403 · Sem permissão

- [`agent_token_out_of_scope`](/erros/agent_token_out_of_scope.md) (HTTP 403): O token de agente (`kat_`) só vale na porta MCP. Para a API, use o token de sessão ou uma chave de integração.
- [`api_key_action_not_granted`](/erros/api_key_action_not_granted.md) (HTTP 403): A chave não tem esta ação. Edite as ações da chave no painel.
- [`api_key_out_of_scope`](/erros/api_key_out_of_scope.md) (HTTP 403): A chave só vale nas rotas do contrato público.
- [`depot_out_of_reach`](/erros/depot_out_of_reach.md) (HTTP 403): Quem chama não alcança o CD deste objeto. Peça alcance ao CD ou use outra credencial.
- [`forbidden_role`](/erros/forbidden_role.md) (HTTP 403): O papel de quem chama nesta empresa não permite esta ação.
- [`module_not_subscribed`](/erros/module_not_subscribed.md) (HTTP 403): A empresa não assina o módulo desta rota.
- [`tenant_mismatch`](/erros/tenant_mismatch.md) (HTTP 403): A credencial não pertence à empresa do endereço chamado.
- [`tenant_unavailable`](/erros/tenant_unavailable.md) (HTTP 403): A empresa está indisponível no momento.

### HTTP 404 · Não encontrado

- [`depot_not_found`](/erros/depot_not_found.md) (HTTP 404): Não existe CD com esse `depot_code` nesta empresa.

### HTTP 409 · Conflito

- [`depot_inactive`](/erros/depot_inactive.md) (HTTP 409): O CD está fechado. Reabra o CD antes de mexer no que está dentro dele.
- [`no_active_depot`](/erros/no_active_depot.md) (HTTP 409): A empresa não tem CD ativo; sem `depot_code`, não há CD a usar.

### HTTP 422 · Não processável

- [`invalid_status`](/erros/invalid_status.md) (HTTP 422): Situação inválida para este filtro ou campo: use um dos valores declarados.

### HTTP 429 · Muitos pedidos

- [`rate_limited`](/erros/rate_limited.md) (HTTP 429): Muitos pedidos por segundo com esta chave. Espere o `Retry-After`, em segundos, e tente de novo.

#### curl

**Lista o saldo de um CD, posição por posição e lote por lote**

```sh
curl -X GET "https://stag.kernos.com.br/v1/objects/stock?limit=20" \
  -H "Authorization: Bearer ksk_test_…" \
  -H "Kernos-Version: 2026-10-03"
```

#### Node

**Lista o saldo de um CD, posição por posição e lote por lote**

```js
import { Kernos } from '@kernosbr/kernos'

const kernos = new Kernos(process.env.KERNOS_API_KEY)
const result = await kernos.stock.list({ limit: 20 })
```

#### Python

**Lista o saldo de um CD, posição por posição e lote por lote**

```python
import os
from kernos import Kernos

kernos = Kernos(os.environ["KERNOS_API_KEY"])
result = kernos.stock.list({"limit": 20})
```

#### PHP

**Lista o saldo de um CD, posição por posição e lote por lote**

```php
<?php
$kernos = new Kernos\Kernos(getenv('KERNOS_API_KEY'));
$result = $kernos->stock->list(['limit' => 20]);
```

#### Java

**Lista o saldo de um CD, posição por posição e lote por lote**

```java
Kernos kernos = new Kernos(System.getenv("KERNOS_API_KEY"));
JsonNode result = kernos.stock().list(Map.of("limit", 20));
```

#### C#

**Lista o saldo de um CD, posição por posição e lote por lote**

```csharp
var kernos = new KernosClient(Environment.GetEnvironmentVariable("KERNOS_API_KEY"));
var result = await kernos.Stock.ListAsync(new Dictionary<string, object?> { ["limit"] = 20 });
```

#### Go

**Lista o saldo de um CD, posição por posição e lote por lote**

```go
client, err := kernos.New(os.Getenv("KERNOS_API_KEY"))
result, err := client.Stock.List(ctx, map[string]any{"limit": 20})
```

#### Rust

**Lista o saldo de um CD, posição por posição e lote por lote**

```rust
let kernos = Kernos::new(&std::env::var("KERNOS_API_KEY")?)?;
let result = kernos.stock().list(Some(&json!({ "limit": 20 })), None)?;
```

**Resposta · 200 (a forma, sem dado real)**

```json
{
  "ok": true,
  "data": {
    "depot_code": "…",
    "limit": 0,
    "offset": 0,
    "stock": [
      {
        "description": "…",
        "ean": "…",
        "expires_on": "…",
        "expiry": "expired",
        "location_code": "…",
        "lot_code": "…",
        "product_id": "3f1e0c8a-5b7d-4c21-9a3e-0b1c2d3e4f50",
        "qty_available": 0,
        "qty_held": 0,
        "qty_on_hand": 0,
        "sku": "…",
        "status": "…",
        "updated_at": "2026-10-03T12:00:00Z"
      }
    ],
    "total": 0,
    "units": 0
  },
  "error": null,
  "error_code": null,
  "field": null,
  "trace_id": null
}
```

> **Ambiente** `ksk_test_` fala com `https://stag.kernos.com.br`; `ksk_live_`, com `https://api.kernos.com.br`. O prefixo da chave escolhe o endereço.
