# API Unidade Regional

Documentação oficial para as regionais que desejam consumir a API do SUCESU para criar notícias e gerenciar associados.

---

## Sumário

1. [Visão Geral](#visao-geral)
2. [Swagger / OpenAPI](#swagger--openapi)
3. [Autenticação](#autenticacao)
4. [Rate Limiting](#rate-limiting)
5. [Endpoints](#endpoints)
   - [POST /noticias (criar)](#post-noticias)
   - [GET /noticias (listar)](#get-noticias)
   - [DELETE /noticias/{id} (arquivar)](#delete-noticiasid)
   - [POST /associados (criar/vincular/atualizar)](#post-associados)
   - [GET /associados (listar)](#get-associados)
   - [DELETE /associados/{id} (arquivar)](#delete-associadosid)
5. [Formato de Resposta](#formato-de-resposta)
6. [Códigos de Erro](#codigos-de-erro)
7. [Exemplos Práticos](#exemplos-praticos)
8. [Dicas de Integração](#dicas-de-integracao)
   - [Arquivos de Exemplo Completos](#arquivos-de-exemplo-completos)
9. [Perguntas Frequentes](#perguntas-frequentes)

---

## Visão Geral

A API Unidade Regional permite que cada filial/regional do SUCESU publique notícias e gerencie associados de forma programática, sem precisar acessar o CMS.

| Item | Detalhe |
|------|---------|
| **URL Base** | `https://seu-dominio.com/api/v2/unidaderegional/` |
| **Formato** | JSON (`Content-Type: application/json`) |
| **Autenticação** | Bearer Token (via header `Authorization`) |
| **Métodos** | `GET`, `POST`, `DELETE` |
| **Codificação** | UTF-8 |
| **OpenAPI** | [Spec JSON](../api/unidaderegional/openapi.json) — importável em Swagger, Postman, Insomnia |

---

## Swagger / OpenAPI

A API disponibiliza uma especificação OpenAPI 3.0 completa para importação em ferramentas de teste e documentação.

### Acesso via CMS

1. Acesse **CMS > Unidades Regionais > [sua regional] > Editar**
2. Clique no botão **"API Docs"** (canto superior direito)
3. A página de documentação inclui:
   - **Swagger UI interativo** — teste endpoints diretamente no navegador
   - **Exemplos de código** — PHP, Laravel, Node.js, Python, Ruby, Rust
   - **Tabela de endpoints** — todos os 6 endpoints documentados
   - **URL do OpenAPI spec** — copie para importar em ferramentas externas

### Importar em Ferramentas Externas

| Ferramenta | Como importar |
|-----------|---------------|
| **Postman** | Import > Link > cole a URL do spec |
| **Swagger Editor** | File > Import URL > cole a URL |
| **VS Code** | Instale extensão "OpenAPI (Swagger) Editor" > cole a URL |
| **Insomnia** | File > Import > From URL |

**URL do Spec:**
```
https://seu-dominio.com/api/v2/unidaderegional/openapi.json
```

### Swagger UI Online (copie o JSON)

Acesse `https://editor.swagger.io` e cole o conteúdo de `openapi.json` para visualizar e testar a API online.

---

## Autenticação

Todas as requisições exigem um **Bearer Token** válido. O token é gerado pelo administrador no CMS em **CMS > Unidades Regionais > [sua regional] > Token de API**.

### Formato do Token

O token começa com `asc_` seguido de 60 caracteres aleatórios. **Salve o token em local seguro** — ele não será exibido novamente após a geração.

```
asc_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789abcdefghijklmnopqrstuvwx
```

### Como Enviar

Inclua o header `Authorization` em todas as requisições:

```bash
curl -H "Authorization: Bearer asc_SEU_TOKEN_AQUI" \
     https://seu-dominio.com/api/v2/unidaderegional/noticias
```

### Validação do Token

O sistema valida o token em cada requisição:

1. Hash SHA-256 do token recebido
2. Busca no banco de dados pelo hash
3. Verifica se não expirou (TTL padrão: 365 dias)
4. Registra o horário do último uso

### Erros de Autenticação

| HTTP | Tipo | Significado |
|------|------|-------------|
| 401 | `invalid_token` | Token não fornecido, inválido ou regional não encontrada |
| 401 | `token_expired` | Token expirado — solicite novo token no CMS |

### Como Obter um Token

1. Acesse o CMS: `https://seu-dominio.com/cms`
2. Navegue até **Unidades Regionais**
3. Clique na sua regional
4. Na aba **Token de API**, clique em **Gerar Token**
5. **Copie e salve** o token exibido — ele aparece apenas uma vez

---

## Rate Limiting

Para proteger a API contra uso excessivo, existem limites de requisição:

| Rota | Limite por Token | Limite por IP |
|------|------------------|---------------|
| `POST /noticias` | 30 req/min | 100 req/min |
| `POST /associados` | 30 req/min | 100 req/min |
| `GET /noticias` | Sem limite | Sem limite |
| `GET /associados` | Sem limite | Sem limite |
| `DELETE /associados/{id}` | Sem limite | Sem limite |

Quando o limite é atingido, a API retorna HTTP `429` com headers:

```
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
Retry-After: 45
```

---

## Endpoints

### POST /noticias

Cria uma nova notícia ou atualiza uma existente para a unidade regional autenticada.

**URL:** `POST /api/v2/unidaderegional/noticias`

#### Modo 1: Criar Nova Notícia (sem `id`)

Todos os campos exceto `title` e `content` são opcionais.

| Campo | Obrigatório | Tipo | Máximo | Descrição |
|-------|-------------|------|--------|-----------|
| `title` | **Sim** | string | 255 | Título da notícia |
| `content` | **Sim** | string | 100.000 | Conteúdo em formato Markdown |
| `subtitle` | Não | string | 500 | Subtítulo da notícia |
| `summary` | Não | string | 1.000 | Resumo da notícia |
| `cover_image_url` | Não | string (URL) | 500 | URL pública da imagem de capa |
| `author_name` | Não | string | 255 | Nome do autor |
| `responsible_name` | Não | string | 255 | Nome do responsável |
| `source` | Não | string | 2.000 | Fonte da notícia |
| `content_date` | Não | string (data) | — | Data do conteúdo (formato: `YYYY-MM-DD`) |
| `tags` | Não | array | 10 tags | Lista de tags (máx. 50 chars cada) |
| `published_at` | Não | string (data) | — | Data de publicação (formato: `YYYY-MM-DD`) |

**Exemplo de Requisição:**

```json
{
  "title": "SUCESU Participa de Fórum Nacional",
  "content": "## Título da Matéria\n\nA regional **SUCESU-DF** participou do fórum nacional de sindicatos.\n\n- Item 1\n- Item 2\n\n![Foto](https://exemplo.com/foto.jpg)",
  "subtitle": "Representantes de todo o país se reuniram",
  "summary": "Discussões sobre novas políticas trabalhistas",
  "author_name": "Assessoria de Comunicação",
  "responsible_name": "João Silva",
  "source": "Assessoria de Comunicação SUCESU-DF",
  "content_date": "2026-07-30",
  "tags": ["fórum", "nacional", "sindical"]
}
```

**Requisição com curl:**

```bash
curl -X POST "https://seu-dominio.com/api/v2/unidaderegional/noticias" \
  -H "Authorization: Bearer asc_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "SUCESU Participa de Fórum Nacional",
    "content": "## Conteúdo da notícia em Markdown",
    "author_name": "Comunicação"
  }'
```

**Resposta de Sucesso (HTTP 201):**

```json
{
  "ok": true,
  "error": null,
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "title": "SUCESU Participa de Fórum Nacional",
    "slug": "sucesu-participa-de-forum-nacional",
    "status": "pending_approval",
    "created_at": "2026-07-30T14:30:00+00:00"
  },
  "message": "Notícia recebida e pendente de aprovação."
}
```

**O que acontece ao criar uma notícia:**

1. A notícia é criada com status `pending_approval` (pendente de aprovação)
2. O conteúdo Markdown é convertido automaticamente para JSON Tiptap (formato do editor do CMS)
3. Se `cover_image_url` for informado, a imagem é baixada e armazenada no servidor
4. Se houver imagens no conteúdo Markdown, elas também são baixadas automaticamente
5. A categoria "regionais" é atribuída automaticamente
6. Uma tag com a sigla da regional (ex: `SUC-TST`) é criada/sincronizada
7. O cache de páginas públicas é invalidado
8. Um log de auditoria é registrado

**Notas importantes:**
- O conteúdo deve estar em **Markdown** — o sistema converte para o formato do editor automaticamente
- Imagens remotas (tanto de capa quanto inline no conteúdo) são baixadas e hospedadas no servidor
- A notícia fica pendente de aprovação — um administrador deve aprová-la no CMS

#### Modo 2: Atualizar Notícia Existente (com `id`)

Envie o campo `id` da notícia para atualizar campos específicos. Apenas os campos enviados são alterados (atualização parcial).

| Campo | Obrigatório | Tipo | Máximo | Descrição |
|-------|-------------|------|--------|-----------|
| `id` | **Sim** | string (UUID) | 36 | ID da notícia a ser atualizada |
| `title` | Não | string | 255 | Novo título |
| `content` | Não | string | 100.000 | Novo conteúdo (Markdown) |
| `subtitle` | Não | string | 500 | Novo subtítulo |
| `summary` | Não | string | 1.000 | Novo resumo |
| `cover_image_url` | Não | string (URL) | 500 | Nova imagem de capa |
| `author_name` | Não | string | 255 | Nome do autor |
| `responsible_name` | Não | string | 255 | Nome do responsável |
| `source` | Não | string | 2.000 | Fonte da notícia |
| `content_date` | Não | string (data) | — | Data do conteúdo |
| `tags` | Não | array | 10 tags | Nova lista de tags |
| `published_at` | Não | string (data) | — | Data de publicação |

**Exemplo — Atualizar título:**

```bash
curl -X POST "https://seu-dominio.com/api/v2/unidaderegional/noticias" \
  -H "Authorization: Bearer asc_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"f47ac10b-58cc-4372-a567-0e02b2c3d479","title":"Novo Título da Matéria"}'
```

**Resposta de Sucesso (HTTP 200):**

```json
{
  "ok": true,
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "title": "Novo Título da Matéria",
    "slug": "novo-titulo-da-materia",
    "status": "pending_approval",
    "updated_at": "2026-07-31T10:00:00+00:00"
  },
  "message": "Notícia atualizada com sucesso."
}
```

**Erros Possíveis:**

| HTTP | Tipo | Significado |
|------|------|-------------|
| 404 | `not_found` | Notícia não encontrada ou não pertence à sua regional |
| 409 | `archived_cannot_reactivate` | Não é possível reativar uma notícia arquivada na nacional |

---

### GET /noticias

Lista as notícias criadas pela unidade regional autenticada.

**URL:** `GET /api/v2/unidaderegional/noticias`

**Parâmetros de Query (opcionais):**

| Parâmetro | Tipo | Padrão | Descrição |
|-----------|------|--------|-----------|
| `per_page` | integer | 15 | Itens por página |

**Exemplo de Requisição:**

```bash
curl -H "Authorization: Bearer asc_SEU_TOKEN" \
  "https://seu-dominio.com/api/v2/unidaderegional/noticias?per_page=10"
```

**Resposta de Sucesso (HTTP 200):**

```json
{
  "ok": true,
  "error": null,
  "data": {
    "unidade_regional_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "total": 25,
    "current_page": 1,
    "last_page": 3,
    "news": [
      {
        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "title": "SUCESU Participa de Fórum Nacional",
        "slug": "sucesu-participa-de-forum-nacional",
        "status": "pending_approval",
        "created_at": "2026-07-30T14:30:00+00:00"
      },
      {
        "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
        "title": "Novo Convênio com Hospital",
        "slug": "novo-convenio-com-hospital",
        "status": "approved",
        "created_at": "2026-07-28T10:00:00+00:00"
      }
    ]
  },
  "message": "Lista de notícias recuperada com sucesso."
}
```

**Nota:** A listagem retorna **apenas** as notícias da sua regional (identificada pelo token). Cada regional só enxerga suas próprias notícias.

---

### DELETE /noticias/{id}

Arquiva (soft-delete) uma notícia da unidade regional autenticada. A notícia é removida do sistema mas seus dados são preservados internamente.

**URL:** `DELETE /api/v2/unidaderegional/noticias/{id}`

**Parâmetro de URL:**

| Parâmetro | Tipo | Descrição |
|-----------|------|-----------|
| `id` | string (UUID) | ID da notícia |

**Exemplo de Requisição:**

```bash
curl -X DELETE "https://seu-dominio.com/api/v2/unidaderegional/noticias/f47ac10b-58cc-4372-a567-0e02b2c3d479" \
  -H "Authorization: Bearer asc_SEU_TOKEN"
```

**Resposta de Sucesso (HTTP 200):**

```json
{
  "ok": true,
  "error": null,
  "data": null,
  "message": "Notícia arquivada com sucesso."
}
```

**Erros Possíveis:**

| HTTP | Tipo | Significado |
|------|------|-------------|
| 404 | `not_found` | Notícia não encontrada ou não pertence à sua regional |
| 409 | `already_archived` | Notícia já foi arquivada anteriormente |

---

### POST /associados

Vincula associados existentes, cria novos ou atualiza associados para a unidade regional autenticada.

**URL:** `POST /api/v2/unidaderegional/associados`

A API aceita três modos de operação:

#### Modo 1: Vincular Associados Existentes

Use quando o associado já está cadastrado no sistema e você apenas quer vinculá-lo à sua regional.

| Campo | Obrigatório | Tipo | Descrição |
|-------|-------------|------|-----------|
| `empresa_ids` | **Sim** | array de strings | Lista de IDs (UUIDs) dos associados existentes |
| `status` | Não | string | `active` (padrão) ou `inactive` |
| `tags` | Não | string | Tags separadas por vírgula (ex: `"destaque, parceiro"`) |

**Exemplo:**

```json
{
  "empresa_ids": [
    "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  ],
  "status": "active",
  "tags": "destaque, parceiro"
}
```

#### Modo 2: Criar Novo Associado

Use quando o associado não existe no sistema ainda. O campo `description` aceita **Markdown** que é convertido automaticamente para o formato rich text do CMS.

| Campo | Obrigatório | Tipo | Descrição |
|-------|-------------|------|-----------|
| `name` | **Sim** | string | Nome do associado (máx. 255) |
| `description` | Não | string | Descrição em formato **Markdown** (convertida para rich text automaticamente) |
| `url` | Não | string (URL) | Site do associado |
| `discount_badge` | Não | string | Texto do selo de desconto |
| `benefits_list` | Não | string | Lista de benefícios |
| `status` | Não | string | `active` (padrão) ou `inactive` |
| `tags` | Não | string | Tags separadas por vírgula |

**Exemplo — descrição em Markdown:**

```json
{
  "name": "Hospital São Lucas",
  "description": "## Sobre o Convênio\n\nO Hospital São Lucas oferece **15% de desconto** em consultas para sócios da SUCESU.\n\n### Benefícios\n\n- Consultas com desconto\n- Exames laboratoriais\n- Cirurgias com condições especiais\n\n### Contato\n\n📞 (61) 3333-4444\n📧 convenio@hospitalsaolucas.com.br",
  "url": "https://hospitalsaolucas.com.br",
  "discount_badge": "15% OFF",
  "tags": "saúde, desconto, destaque",
  "status": "active"
}
```

**Requisição com curl:**

```bash
curl -X POST "https://seu-dominio.com/api/v2/unidaderegional/associados" \
  -H "Authorization: Bearer asc_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Hospital São Lucas",
    "description": "## Convênio\n\nDesconto de **15%** em consultas.",
    "tags": "saúde, desconto"
  }'
```

**Resposta de Sucesso (HTTP 201):**

```json
{
  "ok": true,
  "error": null,
  "data": {
    "results": [
      {
        "empresa_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "success": true,
        "action": "created"
      }
    ]
  },
  "message": "Associados sincronizados com sucesso."
}
```

**O que acontece ao criar um associado:**

1. O campo `description` (Markdown) é convertido para JSON Tiptap (formato rich text do CMS)
2. O Markdown original é preservado em `metadata.source_description_markdown` para referência
3. A categoria `regional` é atribuída automaticamente
4. Tags são criadas/sincronizadas (a primeira tag é marcada como primária)
5. O cache de páginas públicas é invalidado
6. Um log de auditoria é registrado

**Notas importantes:**
- A `description` deve estar em **Markdown** — o sistema converte para rich text automaticamente
- O Markdown original é preservado no campo `metadata.source_description_markdown`
- Imagens inline no Markdown são baixadas e hospedadas automaticamente

#### Modo 3: Atualizar Associado Existente (com `id`)

Envie o campo `id` do associado (AssociadoInstituicao) para atualizar campos específicos. Apenas os campos enviados são alterados (atualização parcial).

| Campo | Obrigatório | Tipo | Descrição |
|-------|-------------|------|-----------|
| `id` | **Sim** | string (UUID) | ID do associado (AssociadoInstituicao) |
| `name` | Não | string | Novo nome (máx. 255) |
| `description` | Não string | Nova descrição em Markdown (convertida para rich text) |
| `url` | Não | string (URL) | Novo site |
| `discount_badge` | Não | string | Novo selo de desconto |
| `benefits_list` | Não | string | Nova lista de benefícios |
| `status` | Não | string | `active` ou `inactive` (atualiza o vínculo) |
| `tags` | Não | string | Novas tags separadas por vírgula |

**Exemplo — Atualizar nome e descrição:**

```bash
curl -X POST "https://seu-dominio.com/api/v2/unidaderegional/associados" \
  -H "Authorization: Bearer asc_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"f47ac10b-58cc-4372-a567-0e02b2c3d479","name":"Hospital São Lucas - Atualizado","description":"## Nova Descrição\n\nConvênio renovado com **20% de desconto**."}'
```

**Resposta de Sucesso (HTTP 200):**

```json
{
  "ok": true,
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "name": "Hospital São Lucas - Atualizado",
    "slug": "hospital-sao-lucas-atualizado",
    "updated_at": "2026-07-31T10:00:00+00:00"
  },
  "message": "Associado atualizado com sucesso."
}
```

**Erros Possíveis:**

| HTTP | Tipo | Significado |
|------|------|-------------|
| 403 | `forbidden` | Associado não está vinculado à sua regional |
| 404 | `not_found` | Associado não encontrado |
| 409 | `archived_cannot_reactivate` | Não é possível reativar um associado arquivado na nacional |

---

### GET /associados

Lista os associados vinculados à unidade regional autenticada.

**URL:** `GET /api/v2/unidaderegional/associados`

**Exemplo de Requisição:**

```bash
curl -H "Authorization: Bearer asc_SEU_TOKEN" \
  "https://seu-dominio.com/api/v2/unidaderegional/associados"
```

**Resposta de Sucesso (HTTP 200):**

```json
{
  "ok": true,
  "error": null,
  "data": {
    "unidade_regional_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "total": 2,
    "associados": [
      {
        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "empresa_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "status": "active",
        "nome": "Hospital São Lucas",
        "slug": "hospital-sao-lucas",
        "logo": null,
        "category": "regional",
        "tags": [
          {
            "id": "tag-1",
            "name": "saúde",
            "slug": "saude",
            "is_primary": true
          }
        ],
        "created_at": "2026-07-30T14:30:00+00:00"
      }
    ]
  },
  "message": "Lista de associados recuperada com sucesso."
}
```

**Nota:** A listagem retorna **apenas** os associados da sua regional (identificada pelo token).

---

### DELETE /associados/{id}

Arquiva (soft-delete) um associado no sistema nacional e remove seu vínculo com a unidade regional. O associado e o vínculo são preservados internamente mas removidos das consultas.

**URL:** `DELETE /api/v2/unidaderegional/associados/{id}`

**Parâmetro de URL:**

| Parâmetro | Tipo | Descrição |
|-----------|------|-----------|
| `id` | string (UUID) | ID do vínculo (UnidadeRegionalEmpresa), não do associado |

**Exemplo de Requisição:**

```bash
curl -X DELETE "https://seu-dominio.com/api/v2/unidaderegional/associados/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -H "Authorization: Bearer asc_SEU_TOKEN"
```

**Resposta de Sucesso (HTTP 200):**

```json
{
  "ok": true,
  "error": null,
  "data": null,
  "message": "Associado arquivado com sucesso."
}
```

**Erros Possíveis:**

| HTTP | Tipo | Significado |
|------|------|-------------|
| 404 | `not_found` | Vínculo não encontrado ou não pertence à sua regional |

---

## Formo de Resposta

Todas as respostas seguem o padrão:

```json
{
  "ok": true | false,
  "error": null | { "title": "...", "detail": "...", "type": "..." },
  "data": { ... } | null,
  "message": "..."
}
```

| Campo | Tipo | Descrição |
|-------|------|-----------|
| `ok` | boolean | `true` se sucesso, `false` se erro |
| `error` | object|null | Detalhes do erro (apenas quando `ok: false`) |
| `data` | mixed | Dados da resposta (varia por endpoint) |
| `message` | string | Mensagem descritiva |

---

## Códigos de Erro

| HTTP | Tipo | Significado | Ação |
|------|------|-------------|------|
| 401 | `invalid_token` | Token não fornecido ou inválido | Verifique o token no CMS |
| 401 | `token_expired` | Token expirado | Gere um novo token no CMS |
| 403 | `forbidden` | Associado não vinculado à sua regional | Vincule o associado primeiro |
| 404 | `not_found` | Recurso não encontrado | Verifique o ID informado |
| 409 | `archived_cannot_reactivate` | Não é possível reativar registro arquivado | Crie um novo registro |
| 409 | `already_archived` | Registro já foi arquivado | Nenhuma ação necessária |
| 422 | `validation_error` | Dados inválidos | Verifique os campos obrigatórios |
| 429 | `too_many_requests` | Limite de requisições atingido | Aguarde o tempo indicado no header `Retry-After` |
| 500 | `server_error` | Erro interno do servidor | Tente novamente ou contate o suporte |

---

## Exemplos Práticos

### Criar notícia completa

```bash
curl -X POST "https://seu-dominio.com/api/v2/unidaderegional/noticias" \
  -H "Authorization: Bearer asc_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "SUCESU-DF Participa de Fórum Nacional",
    "content": "## Resumo\n\nA regional SUCESU-DF esteve representada no fórum nacional.\n\n### Participantes\n\n- João Silva (presidente)\n- Maria Santos (diretora)\n\n![Foto do evento](https://exemplo.com/foto.jpg)",
    "subtitle": "Representantes de todo o país se reuniram em Brasília",
    "author_name": "Assessoria de Comunicação",
    "tags": ["fórum", "nacional", "DF"]
  }'
```

### Criar associado com descrição rica

```bash
curl -X POST "https://seu-dominio.com/api/v2/unidaderegional/associados" \
  -H "Authorization: Bearer asc_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "AutoPosto SUCESU",
    "description": "## Convênio de Combustível\n\nDesconto de **R$ 0,15/litro** para sócios.\n\n### Como usar\n\n1. Apresente o cartão de sócio\n2. Informe o código da regional\n3. O desconto é aplicado automaticamente\n\n### Horário de funcionamento\n\n- Seg a Sex: 6h às 22h\n- Sáb: 6h às 18h",
    "url": "https://autoposto.com",
    "discount_badge": "R$ 0,15/L OFF",
    "tags": "combustível, desconto, posto"
  }'
```

### Listar notícias paginadas

```bash
curl -H "Authorization: Bearer asc_SEU_TOKEN" \
  "https://seu-dominio.com/api/v2/unidaderegional/noticias?per_page=5"
```

### Listar associados

```bash
curl -H "Authorization: Bearer asc_SEU_TOKEN" \
  "https://seu-dominio.com/api/v2/unidaderegional/associados"
```

### Atualizar notícia

```bash
curl -X POST "https://seu-dominio.com/api/v2/unidaderegional/noticias" \
  -H "Authorization: Bearer asc_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"ID_DA_NOTICIA","title":"Título Atualizado","subtitle":"Novo subtítulo"}'
```

### Atualizar associado

```bash
curl -X POST "https://seu-dominio.com/api/v2/unidaderegional/associados" \
  -H "Authorization: Bearer asc_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":"ID_DO_ASSOCIADO","name":"Nome Atualizado","description":"Nova descrição em Markdown."}'
```

### Arquivar notícia

```bash
curl -X DELETE "https://seu-dominio.com/api/v2/unidaderegional/noticias/ID_DA_NOTICIA" \
  -H "Authorization: Bearer asc_SEU_TOKEN"
```

### Arquivar associado

```bash
curl -X DELETE "https://seu-dominio.com/api/v2/unidaderegional/associados/ID_DO_VINCULO" \
  -H "Authorization: Bearer asc_SEU_TOKEN"
```

---

## Dicas de Integração

### Arquivos de Exemplo Completos

Cada linguagem tem um arquivo **único, otimizado e testado** com todas as 6 operações da API (criar, listar, atualizar, arquivar notícias e associados):

| Linguagem | Arquivo | Requisitos |
|-----------|---------|------------|
| **PHP Puro** | [`examples/sucusu_client.php`](examples/sucusu_client.php) | PHP >= 5.4, extensão cURL |
| **PHP Laravel 5.5** | [`examples/SucesuApiClient.php`](examples/SucesuApiClient.php) | Laravel 5.5+, Guzzle |
| **Node.js** | [`examples/sucusu-client.js`](examples/sucusu-client.js) | Node.js >= 18 (fetch nativo) |
| **Python + Flask** | [`examples/sucusu_client.py`](examples/sucusu_client.py) | Python 3.6+, Flask, requests |
| **Rust** | [`examples/main.rs`](examples/main.rs) | reqwest, tokio, serde_json |
| **Ruby on Rails** | [`examples/sucusu_client.rb`](examples/sucusu_client.rb) | HTTParty gem |

#### Como Usar

Cada arquivo pode ser executado standalone (via CLI) ou importado como módulo/classe. A configuração é feita via variáveis de ambiente:

```bash
export SUCESU_API_BASE="https://seu-dominio.com/api/v2/unidaderegional"
export SUCESU_API_TOKEN="asc_SEU_TOKEN"
```

**PHP Puro:**
```bash
php examples/sucusu_client.php
```

**Laravel 5.5 (dentro de um Artisan Command):**
```php
$client = new \SucesuApiClient($token);
$r = $client->criarNoticia(['title' => 'Olá', 'content' => '...']);
```

**Node.js:**
```bash
node examples/sucusu-client.js
```

**Python Flask:**
```bash
# Modo servidor (proxy para a API)
python examples/sucusu_client.py

# Modo teste (executa todas as operações)
python examples/sucusu_client.py --test
```

**Rust:**
```bash
# Adicione o Cargo.toml com as dependências listadas no cabeçalho do arquivo
cargo run
```

**Ruby on Rails:**
```bash
ruby examples/sucusu_client.rb
```

### Snippets Rápidos

Para apenas um trecho de código, veja abaixo:

<details>
<summary><strong>PHP (cURL) — Listar notícias</strong></summary>

```php
$ch = curl_init('https://seu-dominio.com/api/v2/unidaderegional/noticias');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer asc_SEU_TOKEN',
        'Content-Type: application/json',
    ],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);

foreach ($data['data']['news'] as $n) {
    echo $n['title'] . PHP_EOL;
}
```

</details>

<details>
<summary><strong>JavaScript (fetch) — Criar notícia</strong></summary>

```javascript
const resp = await fetch('https://seu-dominio.com/api/v2/unidaderegional/noticias', {
    method: 'POST',
    headers: {
        'Authorization': 'Bearer asc_SEU_TOKEN',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({ title: 'Nova', content: '## Olá' }),
});
const data = await resp.json();
console.log(data.ok ? data.data.id : data.error);
```

</details>

<details>
<summary><strong>Python (requests) — Criar associado</strong></summary>

```python
import requests
r = requests.post(
    'https://seu-dominio.com/api/v2/unidaderegional/associados',
    headers={'Authorization': 'Bearer asc_SEU_TOKEN'},
    json={'name': 'Hospital', 'description': '## Convênio'},
)
print(r.json())
```

</details>

---

## Perguntas Frequentes

### Posso usar a mesma API para múltiplas regionais?

Não. Cada token está vinculado a **uma única regional**. A autenticação é feita pelo token — não existe parâmetro para trocar de regional.

### O que acontece se eu enviar Markdown incorreto?

O sistema converte o Markdown da melhor forma possível. Se houver erros de formatação, eles serão preservados na conversão. Recomendamos testar o Markdown antes de enviar.

### Como faço para verificar se minha notícia foi aprovada?

Use o endpoint `GET /noticias` para listar suas notícias. Cada notícia retorna o campo `status`:
- `pending_approval` — aguardando aprovação
- `approved` — aprovada e publicada
- `draft` — rascunho

### Posso editar uma notícia após criá-la via API?

Sim. Envie um POST para `/noticias` com o campo `id` da notícia e os campos que deseja alterar. Apenas os campos enviados são atualizados (atualização parcial). Se a notícia foi arquivada, receberá erro 409 — não é possível reativar.

### Posso arquivar uma notícia ou associado?

Sim. Use `DELETE /noticias/{id}` para arquivar uma notícia e `DELETE /associados/{id}` para arquivar um associado. O registro é removido das consultas mas preservado internamente (soft-delete). Não é possível reativar registros arquivados — crie um novo se necessário.

### O que é o campo `source_description_markdown` no metadata?

Quando você cria um associado via API com `description` em Markdown, o sistema converte para rich text (Tiptap JSON) e armazena o Markdown original em `metadata.source_description_markdown` para referência.

### Posso usar imagens inline na descrição do associado?

Sim! O campo `description` aceita Markdown com imagens. O sistema baixa automaticamente as imagens remotas e as armazena no servidor, incluindo-as no conteúdo rich text.

### Onde os IDs para `empresa_ids` vêm do?

Os IDs são UUIDs gerados quando o associado é criado no sistema. Você pode obtê-los listando os associados existentes ou consultando o CMS.

### Posso vincular um associado a múltiplas regionais?

Sim. Cada chamada à API cria um vínculo entre o associado e a sua regional. O mesmo associado pode estar vinculado a diferentes regionais.

### O que acontece se eu tentar vincular um associado que já está vinculado?

O sistema atualiza o status do vínculo existente em vez de criar um duplicado. A resposta incluirá `"action": "updated"` em vez de `"action": "created"`.

### Como obter o ID do vínculo para usar no DELETE?

O ID do vínculo é retornado na resposta do `GET /associados`. Ele é diferente do ID do associado (`empresa_id`). O DELETE usa o ID do **vínculo**, não do associado. Ao arquivar, tanto o vínculo quanto o associado são soft-deletados.

---

## Contato

Em caso de dúvidas ou problemas com a API, entre em contato:

- **Suporte Técnico:** suporte@sucesu.org.br
- **Documentação:** Esta página (atualizada automaticamente)
