# API Documentation

Esta página aborda padrões para documentar APIs usando especificações OpenAPI em todos os serviços da Decentraland.

## Objetivos

Nossa abordagem de documentação de API garante:

* **Padronização** - Especificações OpenAPI consistentes em todos os serviços
* **Automação** - Validação, empacotamento e implantação via GitHub Actions
* **Centralização** - Toda a documentação de serviço publicada através do GitBook
* **Propriedade** - A documentação vive em cada repositório de serviço
* **Acessibilidade** - Referências de API atualizadas e amigáveis para contribuintes

***

## Estrutura do Repositório

Cada repositório de serviço DEVE incluir um `/docs` diretório com a seguinte estrutura:

```bash
/docs
  openapi.yaml        # Fonte de verdade (OpenAPI 3.1)
  openapi.json        # Auto-gerado no CI para Hugo/renderers
  index.html          # Documentação autônoma auto-gerada (opcional)
```

### Requisitos de Arquivo

#### `openapi.yaml`

* **DEVE** ser o arquivo fonte canônico
* **DEVE** usar a especificação OpenAPI 3.1
* **PODE** ter um prefixo identificador do serviço (por exemplo, `worlds-openapi.yaml`)
* **PODE** dividir em `components/` ou `examples/` diretórios, se necessário

#### `openapi.json`

* Auto-gerado durante o CI/CD
* Usado pelo Hugo e outros renderers
* Não editar manualmente

#### `index.html`

* Documentação autônoma auto-gerada
* Construído usando Redocly
* Implantado no GitHub Pages

***

## Padrões OpenAPI

Ao escrever `openapi.yaml`, siga estas convenções para garantir consistência e clareza.

### Resumo do Endpoint

**DEVE** refletir o caminho real do endpoint:

```yaml
# ✅ Bom: Caminho de endpoint claro
paths:
  /world/{world_name}/about:
    get:
      summary: /world/{world_name}/about
      description: Recupera informações sobre um world específico
      
# ❌ Ruim: Resumo genérico
paths:
  /world/{world_name}/about:
    get:
      summary: Obter informações do world
```

### Operation ID

**DEVE** incluir o nome do serviço para unicidade global:

```yaml
# ✅ Bom: operationId com prefixo do serviço
operationId: worldsContentServer_getWorldAbout

# ✅ Bom: Outro exemplo
operationId: socialService_getFriends

# ❌ Ruim: Genérico, pode conflitar
operationId: getAbout
```

**Convenção de nomenclatura**: `{serviceName}_{operationDescription}`

* Use camelCase
* Seja descritivo, mas conciso
* Inclua contexto do método HTTP quando útil (por exemplo, `createUser`, `deleteParcel`)

### Versionamento

**DEVE** use versionamento semântico (`MAJOR.MINOR.PATCH`) em `info.version`:

```yaml
openapi: 3.1.0
info:
  title: Worlds Content Server API
  version: 1.2.0  # Versionamento semântico
  description: API para gerenciar worlds da Decentraland
```

**Regras para incremento de versão**:

* **MAJOR**: Mudanças incompatíveis (quebra de compatibilidade na API)
* **MINOR**: Nova funcionalidade (compatível com versões anteriores)
* **PATCH**: Correções de bugs (compatível com versões anteriores)

### Tags e Agrupamento

**DEVE** use tags para agrupar endpoints relacionados:

```yaml
tags:
  - name: Worlds
    description: Operações de gerenciamento de world
  - name: Deployments
    description: Operações de implantação de world
  - name: Health
    description: Endpoints de verificação de integridade

paths:
  /worlds:
    get:
      tags:
        - Worlds
      summary: /worlds
      operationId: worldsContentServer_listWorlds
      
  /worlds/{world_name}/about:
    get:
      tags:
        - Worlds
      summary: /worlds/{world_name}/about
      operationId: worldsContentServer_getWorldAbout
```

{% hint style="info" %}
As operações são agrupadas por tag na navegação do GitBook. Agrupe endpoints relacionados sob a mesma tag para melhor organização.
{% endhint %}

### Exemplo Completo

```yaml
openapi: 3.1.0
info:
  title: Social Service API
  version: 2.1.0
  description: API para gerenciar interações sociais na Decentraland
  contact:
    name: Decentraland Contributors
    url: https://decentraland.org

servers:
  - url: https://social.decentraland.org
    description: Servidor de produção
  - url: https://social.decentraland.zone
    description: Servidor de staging

tags:
  - name: Friends
    description: Gerenciamento de amigos
  - name: Blocked Users
    description: Operações de bloqueio de usuários

paths:
  /friends:
    get:
      tags:
        - Friends
      summary: /friends
      operationId: socialService_getFriends
      description: Retorna uma lista dos amigos do usuário autenticado
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: Resposta bem-sucedida
          content:
            application/json:
              schema:
                type: object
                properties:
                  friends:
                    type: array
                    items:
                      $ref: '#/components/schemas/Friend'
        '401':
          description: Não autorizado

components:
  schemas:
    Friend:
      type: object
      required:
        - address
        - createdAt
      properties:
        address:
          type: string
          description: Endereço Ethereum do amigo
        createdAt:
          type: string
          format: date-time
          description: Quando a amizade foi estabelecida
```

***

## Desenvolvimento Local

### Visualizar Documentação Localmente

Use o Redocly CLI para visualizar sua documentação OpenAPI:

```bash
# Construir documentação HTML
yarn redocly build-docs docs/openapi.yaml -o docs/index.html

# Então abra docs/index.html no seu navegador
```

### Adicionar ao package.json

Adicione um script de build para conveniência:

```json
{
  "scripts": {
    "build:api": "redocly bundle docs/openapi.yaml -o docs/openapi.json --ext json && redocly build-docs docs/openapi.yaml -o docs/index.html",
    "preview:api": "redocly preview-docs docs/openapi.yaml"
  }
}
```

### Instalar Redocly CLI

```bash
# Usando npm
npm install -g @redocly/cli

# Usando yarn
yarn global add @redocly/cli
```

### Validar Especificação OpenAPI

```bash
# Validar sua especificação
redocly lint docs/openapi.yaml

# Empacotar e validar
redocly bundle docs/openapi.yaml
```

***

## Configuração de Automação

### Passo 1: Configurar Secrets do GitBook

Para publicar specs de API no GitBook, adicione estes secrets ao seu repositório:

**Settings → Secrets and variables → Actions → New repository secret**

| Nome do Secret            | Descrição                          | Onde Encontrar                  |
| ------------------------- | ---------------------------------- | ------------------------------- |
| `GITBOOK_ORGANIZATION_ID` | O ID da sua organização no GitBook | GitBook Settings → Organization |
| `GITBOOK_TOKEN`           | Token da API do GitBook            | GitBook Settings → API Tokens   |

{% hint style="warning" %}
Esses secrets DEVEM ser configurados para que o fluxo de trabalho automatizado publique no GitBook.
{% endhint %}

### Passo 2: Adicionar Workflow do GitHub Actions

Criar `.github/workflows/build-api-docs.yml` no seu repositório:

```yaml
name: build-app-docs

on:
  push:
    branches: [main]
    paths:
      - 'docs/**'
  pull_request:
    paths:
      - 'docs/**'

jobs:
  build:
    uses: decentraland/platform-actions/.github/workflows/apps-docs.yml@main
    with:
      api-spec-file: 'docs/openapi.yaml'
      output-file: 'docs/index.html'
      output-directory: './docs'
      api-spec-name: '{service-name}-api'  # ex.: 'social-service-api'
      node-version: '20'
    secrets: inherit
```

**Parâmetros**:

* `api-spec-file`: Caminho para sua especificação OpenAPI (normalmente `docs/openapi.yaml`)
* `output-file`: Onde gerar docs em HTML
* `output-directory`: Diretório para os arquivos de saída
* `api-spec-name`: Nome único para sua especificação de API (usado no GitBook)
* `node-version`: Versão do Node.js a ser usada

**Este workflow irá**:

1. ✅ Validar a especificação OpenAPI
2. ✅ Empacotar a especificação em um único arquivo
3. ✅ Construir documentação estática em HTML usando Redocly
4. ✅ Implantar automaticamente no GitHub Pages
5. ✅ Publicar a spec no GitBook (se os secrets estiverem configurados)

### Passo 3: Habilitar GitHub Pages

Configure o GitHub Pages no seu repositório:

1. Vá para **Settings → Pages**
2. Em **Build and deployment**:
   * Defina **Source** para **GitHub Actions**
3. Certifique-se de que existe um environment chamado **github-pages**
4. Salvar configurações

Após a primeira execução bem-sucedida do workflow, sua documentação estará disponível em:

* **Docs HTML**: `https://decentraland.github.io/<repo>/index.html`
* **Spec OpenAPI**: `https://decentraland.github.io/<repo>/openapi.yaml`
* **JSON Empacotado**: `https://decentraland.github.io/<repo>/openapi.json`

{% hint style="success" %}
Essas URLs permanecem válidas enquanto o repositório existir e o GitHub Pages estiver habilitado.
{% endhint %}

***

## Adicionando ao GitBook

Uma vez que sua documentação de API esteja implantada, adicione-a à documentação centralizada do GitBook.

### Adição Manual (Processo Atual)

1. Navegue até o espaço do GitBook
2. Vá para a **Referência de API** seção
3. Clique em **Add API Reference**
4. Insira os detalhes do seu serviço:
   * **Name**: O nome do seu serviço (por exemplo, "Social Service")
   * **OpenAPI URL**: `https://decentraland.github.io/{repo-name}/openapi.yaml`
5. Salvar

### Recursos de Integração do GitBook

O GitBook irá automaticamente:

* Analisar sua especificação OpenAPI
* Gerar documentação interativa de API
* Criar navegação de endpoints baseada em tags
* Fornecer funcionalidade "Try it"
* Manter docs sincronizados quando você atualizar a spec

***

## Fluxo de Configuração Completo

### Configuração Inicial

{% @mermaid/diagram content="graph TD
A\[Create /docs/openapi.yaml] --> B\[Add GitHub Actions workflow]
B --> C\[Configure GitBook secrets]
C --> D\[Enable GitHub Pages]
D --> E\[Push to main branch]
E --> F\[Workflow runs automatically]
F --> G\[Docs deployed to GitHub Pages]
G --> H\[Add to GitBook manually]" %}

### Atualizações Contínuas

{% @mermaid/diagram content="graph LR
A\[Update openapi.yaml] --> B\[Create PR]
B --> C\[Workflow validates]
C --> D\[Merge to main]
D --> E\[Auto-deploy to GitHub Pages]
E --> F\[GitBook syncs automatically]" %}

***

## Boas Práticas

### Qualidade da Documentação

* **Seja descritivo**: Escreva resumos e descrições claras
* **Forneça exemplos**: Inclua exemplos de requisição/resposta
* **Documente erros**: Descreva todas as possíveis respostas de erro
* **Use components**: Reutilize schemas via `$ref` para evitar duplicação
* **Adicione descrições**: Todo parâmetro, propriedade e resposta deve ter uma descrição

### Exemplo com Melhores Práticas

```yaml
paths:
  /users/{address}/friends:
    get:
      tags:
        - Friends
      summary: /users/{address}/friends
      operationId: socialService_getUserFriends
      description: |
        Recupera uma lista paginada de amigos para o usuário especificado.
        Retorna endereços de amigos e metadados incluindo quando a amizade foi estabelecida.
      parameters:
        - name: address
          in: path
          required: true
          description: Endereço Ethereum do usuário (com prefixo 0x)
          schema:
            type: string
            pattern: '^0x[a-fA-F0-9]{40}$'
          example: '0x1234567890abcdef1234567890abcdef12345678'
        - name: limit
          in: query
          description: Número máximo de amigos a retornar (1-100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
        - name: offset
          in: query
          description: Número de amigos a pular para paginação
          schema:
            type: integer
            minimum: 0
            default: 0
      responses:
        '200':
          description: Lista de amigos recuperada com sucesso
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FriendsResponse'
              example:
                friends:
                  - address: '0xabcdef...'
                    createdAt: '2024-01-15T10:30:00Z'
                total: 42
                offset: 0
                limit: 50
        '400':
          description: Formato de endereço inválido
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: 'Formato de endereço inválido'
                code: 'INVALID_ADDRESS'
        '404':
          description: Usuário não encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
```

### Reutilização de Schemas

```yaml
components:
  schemas:
    Error:
      type: object
      required:
        - error
        - code
      properties:
        error:
          type: string
          description: Mensagem de erro legível por humanos
        code:
          type: string
          description: Código de erro legível por máquina
        details:
          type: object
          description: Contexto adicional do erro
          
    PaginatedResponse:
      type: object
      required:
        - offset
        - limit
        - total
      properties:
        offset:
          type: integer
          description: Número de itens ignorados
        limit:
          type: integer
          description: Máximo de itens por página
        total:
          type: integer
          description: Número total de itens disponíveis
```

### Schemas de Segurança

```yaml
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Token JWT obtido do endpoint de autenticação

security:
  - BearerAuth: []
```

***

## Validação e Verificações de Qualidade

### Validação Pré-Commit

Adicione um hook pre-commit ou verificação no CI:

```yaml
# .github/workflows/validate-api-spec.yml
name: Validate API Spec

on: [pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '20'
      - run: npm install -g @redocly/cli
      - run: redocly lint docs/openapi.yaml
```

### Regras Comuns de Validação

* Todos os paths têm operation IDs
* Todas as operações têm tags
* Todos os parâmetros têm descrições
* Todas as respostas estão documentadas
* Exemplos são fornecidos
* Schemas são referenciados corretamente

***

## Solução de Problemas

### Workflow Falha

**Problema**: O workflow do GitHub Actions falha

**Soluções**:

* Verifique os logs do workflow para erros de validação
* Execute `redocly lint docs/openapi.yaml` localmente
* Verifique caminhos de arquivos na configuração do workflow
* Certifique-se de que os secrets estejam configurados corretamente

### GitHub Pages Não Funciona

**Problema**: Docs não aparecem na URL do GitHub Pages

**Soluções**:

* Verifique se o GitHub Pages está habilitado nas configurações do repositório
* Verifique se o workflow foi concluído com sucesso
* Aguarde alguns minutos para o GitHub Pages atualizar
* Verifique se o `github-pages` environment existe

### GitBook Não Está Sincronizando

**Problema**: GitBook não mostra docs de API atualizados

**Soluções**:

* Verifique se os secrets do GitBook estão corretos
* Verifique se a URL OpenAPI é acessível
* Dispare manualmente uma atualização no GitBook
* Verifique se a especificação OpenAPI é válida

***

## Migração de Documentação Existente

Se você tiver documentação de API existente:

1. **Exportar para OpenAPI**: Converter docs existentes para o formato OpenAPI 3.1
2. **Validar**: Usar `redocly lint` para garantir conformidade
3. **Adicionar workflow**: Configurar automação do GitHub Actions
4. **Testar**: Verificar se os docs são construídos e implantados corretamente
5. **Atualizar links**: Apontar links da documentação antiga para a nova URL do GitHub Pages
6. **Arquivar documentos antigos**: Manter documentos antigos para referência durante a transição

***

## Próximos Passos

* Revisar o [Well-Known Components](https://github.com/decentraland/docs/blob/main/contributor/contributor-guides/well-known-components/README.md) padrões para implementação de API
* Veja [Padrões de Teste](https://docs.decentraland.org/contributor/contributor-pt/guias-para-contribuidores/testing-standards) para diretrizes de teste de API
* Confira exemplos de API existentes no [Referência de API](https://docs.decentraland.org) seção

## Related Standards

* [Gerenciamento de Dependências](https://docs.decentraland.org/contributor/contributor-pt/guias-para-contribuidores/dependency-management) - Gerenciando dependências npm e peerDependencies
* [Well-Known Components](https://github.com/decentraland/docs/blob/main/contributor/contributor-guides/well-known-components/README.md) - WKC architecture para serviços
* [Padrões de Teste](https://docs.decentraland.org/contributor/contributor-pt/guias-para-contribuidores/testing-standards) - Padrões de teste para serviços

## Recursos

* **OpenAPI Specification**: [spec.openapis.org](https://spec.openapis.org/oas/latest.html)
* **Redocly CLI**: [redocly.com/docs/cli](https://redocly.com/docs/cli/)
* **Integração da API do GitBook**: [docs.gitbook.com](https://docs.gitbook.com)
* **Repositório Platform Actions**: [github.com/decentraland/platform-actions](https://github.com/decentraland/platform-actions)
