# KS API — documentação completa da API v1

Aplicação: **v0.2.0**  
Contrato externo: **API v1, preservado**  
Base URL: `https://ks.api.br`

## 1. Modelo

A API recebe uma imagem, registra um job no MySQL e um worker autônomo executa
a remoção. O cliente pode aguardar uma janela síncrona ou consultar o job. O
processamento não depende de navegador ou estação conectada.

O domínio `remover-fundo.com.br` usa um serviço de sessão próprio e não é um
substituto para esta API. Clientes servidor-servidor devem usar somente
`https://ks.api.br/api/v1` com API Key própria.

## 2. Autenticação

Exceto Health, envie:

```http
Authorization: Bearer KRF_IDENTIFICADOR_SEGREDO
```

Permissões independentes:

| Permissão | Libera |
|---|---|
| `process_image` | criar job |
| `read_job` | capabilities e status dos próprios jobs |
| `read_result` | baixar resultados próprios |

A chave completa é exibida somente quando criada. O banco armazena hash do
segredo. Não grave a chave em JavaScript público, URL, repositório ou log.

## 3. Endpoints

| Método | Caminho | Autenticação | Resultado |
|---|---|---|---|
| GET | `/api/v1/health` | não | banco/storage disponíveis |
| GET | `/api/v1/capabilities` | `read_job` | formatos, limites e workers |
| POST | `/api/v1/process` | `process_image` | cria e opcionalmente aguarda job |
| GET | `/api/v1/jobs/{job_id}` | `read_job` | estado do próprio job |
| GET | `/api/v1/jobs/{job_id}/result` | `read_result` | arquivo concluído |

## 4. Limites técnicos

- HTTPS obrigatório;
- entrada JPEG, PNG ou WEBP;
- entrada máxima padrão: 25 MB;
- até 10.000 px por aresta e 60 MP;
- saída máxima padrão: 50 MB;
- parâmetros de texto e coordenadas têm limites descritos abaixo;
- rate limit é configurado por usuário API.

Consulte `/api/v1/capabilities` para o limite operacional atual.

## 5. Health

```bash
curl -fsS https://ks.api.br/api/v1/health
```

```json
{
  "status": "ok",
  "service": "Kapui Remove Fundo",
  "api_version": "1.0"
}
```

`degraded`/503 indica banco ou storage indisponível. O endpoint não confirma
qualidade do modelo; use Capabilities para saber se há worker online.

## 6. Capabilities

```bash
curl -fsS \
  -H "Authorization: Bearer $KRF_API_KEY" \
  https://ks.api.br/api/v1/capabilities
```

Campos principais: `formats`, `transparent_output`, `trim`, `resize_modes`,
`input_crop_modes`, `crop_coordinate_space`, `processor_available`,
`online_workers` e `max_upload_mb`.

## 7. Criar job

```http
POST /api/v1/process
Content-Type: multipart/form-data
```

### Parâmetros

| Campo | Tipo/padrão | Regra |
|---|---|---|
| `image` | arquivo obrigatório | JPEG, PNG ou WEBP válido |
| `output_format` | `png` | `png`, `webp`, `jpeg` |
| `background` | `transparent` | transparente ou `#RRGGBB`; JPEG exige cor |
| `quality` | `95` | 1–100 para WEBP/JPEG |
| `trim` | `true` | remove área transparente ao redor |
| `margin` | `20` | 0–1000 px depois do trim |
| `normalize_orientation` | `true` | normaliza EXIF |
| `auto_rotate` | `false` | escolhe orientação se houver canvas |
| `rotation` | `0` | 0, 90, 180 ou 270 |
| `canvas_width` | `0` | 0–10000; 0 calcula automaticamente |
| `canvas_height` | `0` | 0–10000 |
| `resize_mode` | `contain` | `original`, `contain`, `fit` |
| `max_width` | `0` | limite 0–10000 |
| `max_height` | `0` | limite 0–10000 |
| `preserve_aspect_ratio` | `true` | sempre preservado |
| `position` | vazio | atalho de posição |
| `horizontal_position` | `center` | `left`, `center`, `right` |
| `vertical_position` | `center` | `top`, `center`, `bottom` |
| `crop_mode` | `none` | `none`, `rectangle`, `polygon` |
| `crop_x` | `0` | coordenada x da origem normalizada |
| `crop_y` | `0` | coordenada y da origem normalizada |
| `crop_width` | `0` | obrigatório no retângulo |
| `crop_height` | `0` | obrigatório no retângulo |
| `crop_polygon` | vazio | JSON com 3–64 pontos inteiros `{x,y}` |
| `response_mode` | `json` | `json` ou `image` |
| `sync` | `true` | aguarda a janela síncrona configurada |
| `source_system` | vazio | referência até 80 caracteres |
| `job_reference` | vazio | até 120 caracteres |
| `product_id` | vazio | até 80 caracteres |
| `client_reference` | vazio | até 160 caracteres |

Booleanos aceitam `true/false`, `1/0`, `yes/no` ou `on/off`.

### Coordenadas do recorte

Use pixels da imagem-fonte depois da normalização de orientação. Retângulo:

```text
crop_mode=rectangle
crop_x=120
crop_y=80
crop_width=900
crop_height=650
```

Polígono:

```json
[
  {"x":120,"y":80},
  {"x":1020,"y":110},
  {"x":940,"y":730},
  {"x":180,"y":700}
]
```

O motor homologado com a v0.2.0 conserva o contexto integral: primeiro infere a imagem
normalizada completa e depois aplica o retângulo/polígono à máscara. Isso evita
que o zoom do recorte mude a classificação de áreas internas do objeto.

### Exemplo cURL assíncrono

```bash
curl -fsS -X POST https://ks.api.br/api/v1/process \
  -H "Authorization: Bearer $KRF_API_KEY" \
  -F "image=@/caminho/produto.jpg" \
  -F "output_format=png" \
  -F "background=transparent" \
  -F "trim=true" \
  -F "margin=20" \
  -F "resize_mode=original" \
  -F "sync=false" \
  -F "source_system=meu-sistema" \
  -F "job_reference=pedido-123"
```

Resposta 202:

```json
{
  "success": true,
  "job_id": "KRF-20260824-AB12CD34",
  "status": "queued",
  "poll_endpoint": "/api/v1/jobs/KRF-20260824-AB12CD34"
}
```

`sync=true` pode responder 200 se concluir na janela ou 202 se continuar na
fila. `response_mode=image` só devolve binário diretamente quando conclui
dentro da janela; caso contrário ainda devolve JSON 202.

## 8. Consultar e baixar

```bash
JOB_ID="KRF-20260824-AB12CD34"
curl -fsS -H "Authorization: Bearer $KRF_API_KEY" \
  "https://ks.api.br/api/v1/jobs/$JOB_ID"
```

Conclusão:

```json
{
  "success": true,
  "job_id": "KRF-20260824-AB12CD34",
  "status": "completed",
  "result": {
    "format": "png",
    "width": 1200,
    "height": 900,
    "size_bytes": 482331,
    "transparent": true,
    "download_endpoint": "/api/v1/jobs/KRF-20260824-AB12CD34/result"
  },
  "duration_ms": 8432
}
```

Download:

```bash
curl -fsS -H "Authorization: Bearer $KRF_API_KEY" \
  "https://ks.api.br/api/v1/jobs/$JOB_ID/result" \
  -o resultado.png
```

## 9. Erros

Formato:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMETER",
    "message": "Mensagem segura.",
    "details": {"parameter":"background"}
  }
}
```

| HTTP | Exemplos | Tratamento |
|---:|---|---|
| 400 | `HTTPS_REQUIRED` | corrigir transporte |
| 401 | credencial ausente/inválida | revisar Bearer |
| 403 | permissão/revogação | revisar chave e permissões |
| 404 | `JOB_NOT_FOUND` | confirmar proprietário e ID |
| 409 | `RESULT_NOT_READY` | continuar polling |
| 413 | `FILE_TOO_LARGE` | respeitar capabilities |
| 415 | `INVALID_REQUEST` | usar multipart/form-data |
| 422 | imagem/parâmetro/crop inválido | corrigir requisição |
| 429 | rate limit | aguardar e aplicar backoff |
| 500 | `INTERNAL_ERROR` | registrar request ID e acionar suporte |
| 503 | serviço/worker indisponível | backoff e nova tentativa segura |

Não repita imediatamente erros 4xx definitivos. Para 429/503 use backoff com
jitter. Guarde `job_id`; não crie jobs duplicados quando apenas o polling falha.

## 10. Segurança do cliente

- guarde API Key em secret manager ou arquivo protegido;
- use um usuário/chave por cliente ou ambiente;
- atribua apenas permissões necessárias;
- não desative verificação TLS;
- valide MIME, tamanho e dimensões antes de enviar;
- não exponha resultado por URL pública sem controle próprio;
- revogue imediatamente chave de host perdido;
- não use token de worker como API Key.

## 11. Ferramentas incluídas

- `/teste/`: formulário visual com todas as opções; chave não persistida;
- `OPENAPI-v1.yaml`: contrato OpenAPI 3.1;
- `OPENAPI-worker-v1.yaml`: reservado ao adaptador, não distribuir a clientes;
- `distribuicao-api/`: cliente PHP protegido e exemplos cURL, PHP, Node e Python.

O formulário de teste é para homologação. Integrações reais devem ser
servidor-servidor e manter a credencial fora do navegador.
