# API Admin

A API Admin fornece endpoints para administracao do sistema, gerenciamento de configuracao, monitoramento e operacoes de arquivos.

## URL Base

```
http://localhost:8081/admin
```

## Autenticacao

Todos os endpoints da API Admin requerem autenticacao HTTP Basic:

```bash
curl -u admin:senha http://localhost:8081/admin/health
```

Ou com header:

```bash
curl -H "Authorization: Basic $(echo -n 'admin:senha' | base64)" \
  http://localhost:8081/admin/health
```

## Endpoints

### Saude

#### Obter Status de Saude

Verificar a saude geral do sistema:

```http
GET /admin/health
```

Resposta (200 OK):

```json
{
  "status": "healthy",
  "version": "1.0.0",
  "checks": {
    "store": "healthy",
    "metrics": "healthy",
    "poller": "idle"
  },
  "timestamp": "2026-01-31T10:30:00Z"
}
```

| Campo | Descricao |
|-------|-----------|
| `status` | Status geral: `healthy`, `degraded`, `unhealthy` |
| `version` | Versao do connector |
| `checks` | Verificacoes de saude dos componentes |
| `timestamp` | Timestamp da verificacao (UTC) |

Valores de status de verificacao:

| Componente | Valores Possiveis |
|------------|-------------------|
| `store` | `healthy`, `unhealthy: {erro}`, `unavailable` |
| `metrics` | `healthy`, `unavailable` |
| `poller` | `polling`, `idle`, `unavailable` |

---

### Configuracao

#### Obter Configuracao

Recuperar a configuracao atual com valores sensiveis ocultados:

```http
GET /admin/config
```

Resposta (200 OK):

```json
{
  "service": {
    "name": "sta-connector",
    "log_level": "info"
  },
  "sta": {
    "environment": "homologation",
    "base_url": "https://sta-h.bcb.gov.br/staws",
    "username": "user123",
    "password": "[OCULTADO]",
    "institution_code": "12345",
    "timeout_seconds": 30,
    "max_retries": 3
  },
  "poller": {
    "enabled": true,
    "interval_seconds": 30,
    "systems": ["CCS", "SPI", "DICT"],
    "batch_size": 10
  },
  "outbound_api": {
    "enabled": true,
    "host": "0.0.0.0",
    "port": 8080,
    "auth": {
      "type": "api_key",
      "key": "[OCULTADO]"
    }
  },
  "admin_api": {
    "enabled": true,
    "host": "0.0.0.0",
    "port": 8081,
    "auth": {
      "username": "admin",
      "password": "[OCULTADO]"
    }
  },
  "routes": {
    "CCS": {
      "enabled": true,
      "url": "https://staapi-planner.monetarie.com.br/api/v1/ccs",
      "method": "POST",
      "timeout_seconds": 30,
      "retry_attempts": 3
    }
  },
  "state_store": {
    "type": "sqlite",
    "sqlite_path": "./data/state.db"
  }
}
```

#### Atualizar Configuracao

Atualizar valores de configuracao em tempo de execucao (hot-reload):

```http
PATCH /admin/config
Content-Type: application/json

{
  "poller": {
    "interval_seconds": 60,
    "batch_size": 20
  },
  "routes": {
    "DICT": {
      "enabled": false
    }
  },
  "service": {
    "log_level": "debug"
  }
}
```

Resposta (200 OK):

```json
{
  "service": {
    "name": "sta-connector",
    "log_level": "debug"
  },
  "poller": {
    "enabled": true,
    "interval_seconds": 60,
    "batch_size": 20
  }
  // ... configuracao completa atualizada
}
```

Resposta de Erro (400 Bad Request):

```json
{
  "error": "poller interval_seconds deve ser positivo",
  "code": "VALIDATION_ERROR",
  "timestamp": "2026-01-31T10:30:00Z"
}
```

Campos atualizaveis:

| Campo | Descricao |
|-------|-----------|
| `service.log_level` | Verbosidade do log |
| `poller.enabled` | Habilitar/desabilitar poller |
| `poller.interval_seconds` | Intervalo de polling |
| `poller.batch_size` | Arquivos por poll |
| `routes.{sistema}.enabled` | Habilitar/desabilitar rota |
| `routes.{sistema}.url` | URL de destino da rota |
| `routes.{sistema}.timeout_seconds` | Timeout da requisicao |
| `routes.{sistema}.retry_attempts` | Contagem de retries |

---

### Metricas

#### Obter Metricas

Recuperar metricas operacionais:

```http
GET /admin/metrics
```

Resposta (200 OK):

```json
{
  "timestamp": "2026-01-31T10:30:00Z",
  "uptime_seconds": 86400,
  "inbound": {
    "files_discovered": 10234,
    "files_processed": 10200,
    "files_failed": 12,
    "files_pending": 22
  },
  "outbound": {
    "files_submitted": 5000,
    "files_uploaded": 4995,
    "files_failed": 3,
    "files_pending": 2
  },
  "poller": {
    "enabled": true,
    "last_poll": "2026-01-31T10:29:00Z",
    "poll_count": 500,
    "avg_poll_duration_ms": 1250
  },
  "sta_client": {
    "requests_total": 50000,
    "requests_failed": 45,
    "avg_latency_ms": 450,
    "rate_limit_remaining": 85
  },
  "system": {
    "memory_mb": 256,
    "goroutines": 50,
    "db_connections": 10
  }
}
```

---

### Arquivos

#### Listar Arquivos

Listar arquivos processados com filtragem opcional:

```http
GET /admin/files?status=failed&system=SPI&limit=50&offset=0
```

Parametros de Query:

| Parametro | Tipo | Padrao | Descricao |
|-----------|------|--------|-----------|
| `status` | string | - | Filtrar por status |
| `system` | string | - | Filtrar por sistema BCB |
| `limit` | integer | 100 | Max resultados (1-1000) |
| `offset` | integer | 0 | Offset de paginacao |
| `start_date` | string | - | Data inicial (ISO 8601 ou DD/MM/AAAA) |
| `end_date` | string | - | Data final (ISO 8601 ou DD/MM/AAAA) |

Resposta (200 OK):

```json
{
  "files": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "protocol": "2026013100001234",
      "file_name": "SPI_20260131_001.xml",
      "file_type": "PACS.008",
      "file_size": 12345,
      "source_system": "SPI",
      "status": "failed",
      "last_error": "connection timeout",
      "retry_count": 3,
      "created_at": "2026-01-31T10:30:00Z",
      "updated_at": "2026-01-31T10:35:00Z"
    }
  ],
  "total": 45,
  "limit": 50,
  "offset": 0,
  "has_more": false
}
```

Valores de status:

| Status | Descricao |
|--------|-----------|
| `pending` | Enfileirado para processamento |
| `uploading` | Upload em progresso |
| `uploaded` | Enviado ao BCB |
| `processing` | BCB esta processando |
| `completed` | Processado com sucesso |
| `failed` | Processamento falhou |
| `retrying` | Agendado para retry |

#### Retentar Arquivo

Retentar um arquivo com falha:

```http
POST /admin/retry/{file_id}
```

Resposta (202 Accepted):

```json
{
  "message": "arquivo enfileirado para retry",
  "file_id": "550e8400-e29b-41d4-a716-446655440000",
  "queued": true,
  "retry_count": 4,
  "timestamp": "2026-01-31T10:30:00Z"
}
```

Resposta de Erro (400 Bad Request):

```json
{
  "error": "apenas arquivos com falha podem ser retentados, status atual: completed",
  "code": "INVALID_STATUS",
  "timestamp": "2026-01-31T10:30:00Z"
}
```

Resposta de Erro (404 Not Found):

```json
{
  "error": "arquivo nao encontrado: 550e8400-...",
  "code": "FILE_NOT_FOUND",
  "timestamp": "2026-01-31T10:30:00Z"
}
```

---

### Controle do Poller

#### Disparar Poll

Disparar manualmente um ciclo de poll:

```http
POST /admin/poller/trigger
```

Resposta (202 Accepted):

```json
{
  "message": "ciclo de poll disparado com sucesso",
  "triggered": true,
  "timestamp": "2026-01-31T10:30:00Z"
}
```

Resposta (409 Conflict) - Poll ja em progresso:

```json
{
  "message": "ciclo de poll ja em progresso",
  "triggered": false,
  "timestamp": "2026-01-31T10:30:00Z"
}
```

---

## Respostas de Erro

Todas as respostas de erro seguem este formato:

```json
{
  "error": "descricao do erro",
  "code": "CODIGO_ERRO",
  "timestamp": "2026-01-31T10:30:00Z"
}
```

### Codigos de Status HTTP

| Codigo | Descricao |
|--------|-----------|
| 200 | Sucesso |
| 202 | Aceito (operacao assincrona) |
| 400 | Requisicao Invalida |
| 401 | Nao Autorizado |
| 404 | Nao Encontrado |
| 409 | Conflito |
| 500 | Erro Interno do Servidor |
| 503 | Servico Indisponivel |

### Codigos de Erro

| Codigo | Descricao |
|--------|-----------|
| `VALIDATION_ERROR` | Validacao da requisicao falhou |
| `INVALID_JSON` | Corpo JSON malformado |
| `INVALID_REQUEST` | Formato de requisicao invalido |
| `INVALID_STATUS` | Status de arquivo invalido para operacao |
| `FILE_NOT_FOUND` | Arquivo nao encontrado |
| `MISSING_FILE_ID` | ID do arquivo nao fornecido |
| `CONFIG_UPDATE_UNAVAILABLE` | Atualizacoes de config nao suportadas |
| `METRICS_UNAVAILABLE` | Coletor de metricas nao disponivel |
| `POLLER_UNAVAILABLE` | Poller nao disponivel |
| `STORE_UNAVAILABLE` | State store nao disponivel |
| `UPDATE_FAILED` | Falha ao aplicar configuracao |
| `TRIGGER_FAILED` | Falha ao disparar poll |
| `GET_FILE_FAILED` | Falha ao recuperar arquivo |
| `UPDATE_STATUS_FAILED` | Falha ao atualizar status do arquivo |
| `RETRY_QUEUE_FAILED` | Falha ao adicionar a fila de retry |
| `LIST_FAILED` | Falha ao listar arquivos |

---

## Exemplos de Codigo

### cURL

```bash
# Health check
curl -u admin:senha http://localhost:8081/admin/health

# Obter configuracao
curl -u admin:senha http://localhost:8081/admin/config

# Atualizar configuracao
curl -u admin:senha -X PATCH http://localhost:8081/admin/config \
  -H "Content-Type: application/json" \
  -d '{"poller": {"interval_seconds": 60}}'

# Obter metricas
curl -u admin:senha http://localhost:8081/admin/metrics

# Listar arquivos com falha
curl -u admin:senha "http://localhost:8081/admin/files?status=failed&limit=10"

# Retentar um arquivo
curl -u admin:senha -X POST http://localhost:8081/admin/retry/550e8400-...

# Disparar poll
curl -u admin:senha -X POST http://localhost:8081/admin/poller/trigger
```

### Python

```python
import requests
from requests.auth import HTTPBasicAuth

auth = HTTPBasicAuth('admin', 'senha')
base_url = 'http://localhost:8081/admin'

# Health check
health = requests.get(f'{base_url}/health', auth=auth).json()
print(f"Status: {health['status']}")

# Obter metricas
metrics = requests.get(f'{base_url}/metrics', auth=auth).json()
print(f"Arquivos processados: {metrics['inbound']['files_processed']}")

# Atualizar configuracao
update = {'poller': {'interval_seconds': 60}}
response = requests.patch(
    f'{base_url}/config',
    auth=auth,
    json=update
)
print(f"Atualizado: {response.status_code == 200}")

# Listar arquivos com falha
files = requests.get(
    f'{base_url}/files',
    auth=auth,
    params={'status': 'failed', 'limit': 10}
).json()

for file in files['files']:
    print(f"Falha: {file['id']} - {file['last_error']}")

    # Retentar o arquivo
    retry = requests.post(f'{base_url}/retry/{file["id"]}', auth=auth)
    print(f"Retry enfileirado: {retry.json()['queued']}")
```

### Node.js

```javascript
const axios = require('axios');

const client = axios.create({
  baseURL: 'http://localhost:8081/admin',
  auth: {
    username: 'admin',
    password: 'senha'
  }
});

async function monitorConnector() {
  // Health check
  const health = await client.get('/health');
  console.log('Status:', health.data.status);

  // Obter metricas
  const metrics = await client.get('/metrics');
  console.log('Arquivos processados:', metrics.data.inbound.files_processed);

  // Listar e retentar arquivos com falha
  const files = await client.get('/files', {
    params: { status: 'failed', limit: 10 }
  });

  for (const file of files.data.files) {
    console.log(`Retentando: ${file.id}`);
    await client.post(`/retry/${file.id}`);
  }
}

monitorConnector().catch(console.error);
```

---

## Proximos Passos

- [API de Saida](/pt/api/outbound) - Endpoints de upload de arquivos
- [Guia de Configuracao](/pt/guide/configuration) - Opcoes de configuracao
- [Solucao de Problemas](/pt/troubleshooting) - Problemas comuns
