API

Documentação da API com Scribe

Este documento explica como usar e manter a documentação da API do AgrSis usando o Scribe.

Documentação da API com Scribe

Este documento explica como usar e manter a documentação da API do AgrSis usando o Scribe.

Índice

  1. O que é o Scribe?
  2. Acessando a Documentação
  3. Como Adicionar/Atualizar Documentação
  4. Tipos de Anotações
  5. Exemplos Práticos
  6. Comandos Úteis
  7. Exportação para Outras Ferramentas
  8. Configuração Avançada

O que é o Scribe?

Scribe é um pacote Laravel que gera automaticamente documentação interativa para sua API a partir das anotações nos controllers.

Principais Funcionalidades:

  • Documentação HTML interativa
  • Exportação para Postman (collection.json)
  • Exportação para OpenAPI/Swagger (openapi.yaml)
  • Exemplos de requisições em múltiplas linguagens (Bash, JavaScript, PHP, Python)
  • Teste de endpoints direto na documentação (Try It Out)
  • Suporte a autenticação (Sanctum, Passport, etc.)

Acessando a Documentação

Localmente (Desenvolvimento)

Após iniciar o servidor:

php artisan serve

Acesse:

Com Docker

docker-compose up -d

Acesse:

Arquivos Exportados

Os arquivos exportados ficam em:

  • Postman Collection: storage/app/private/scribe/collection.json
  • OpenAPI Spec: storage/app/private/scribe/openapi.yaml

Como Adicionar/Atualizar Documentação

Passo 1: Adicionar Anotações no Controller

Adicione anotações PHP DocBlock acima dos métodos do controller:

/**
 * @group Nome do Grupo
 *
 * Descrição do grupo de endpoints
 */
class SeuController extends Controller
{
    /**
     * Título do Endpoint
     *
     * Descrição detalhada do que o endpoint faz.
     *
     * @authenticated
     *
     * @urlParam id integer required ID do recurso. Example: 1
     * @queryParam filter string Filtro opcional. Example: ativo
     * @bodyParam nome string required Nome do recurso. Example: João Silva
     *
     * @response 200 {
     *   "success": true,
     *   "data": {...}
     * }
     */
    public function index(Request $request)
    {
        // ...
    }
}

Passo 2: Gerar a Documentação

Após adicionar ou modificar anotações, execute:

php artisan scribe:generate

Com Docker:

docker exec agrsis_api php artisan scribe:generate

Passo 3: Verificar

Acesse http://localhost:8000/docs para ver as alterações.


Tipos de Anotações

@group

Define o grupo ao qual o endpoint pertence. Geralmente usado na classe do controller.

/**
 * @group Autenticação
 *
 * Endpoints relacionados à autenticação de usuários
 */
class AuthController extends Controller

@authenticated / @unauthenticated

Indica se o endpoint requer autenticação ou não.

/**
 * @authenticated
 */
public function index() // Requer autenticação

/**
 * @unauthenticated
 */
public function login() // Não requer autenticação

@urlParam

Parâmetros na URL (path parameters).

/**
 * @urlParam id integer required ID do produto. Example: 1
 * @urlParam slug string Slug do produto. Example: fertilizante-npk
 */

Formato: @urlParam nome tipo [required] descrição. Example: valor

@queryParam

Parâmetros de query string (?param=valor).

/**
 * @queryParam page integer Número da página. Example: 1
 * @queryParam per_page integer Itens por página. Example: 15
 * @queryParam search string Termo de busca. Example: fertilizante
 * @queryParam ativo boolean required Filtrar por status ativo. Example: true
 */

Formato: @queryParam nome tipo [required] descrição. Example: valor

@bodyParam

Parâmetros no corpo da requisição (POST/PUT/PATCH).

/**
 * @bodyParam nome string required Nome do produto. Example: Fertilizante NPK
 * @bodyParam descricao string Descrição do produto. Example: Fertilizante mineral misto
 * @bodyParam preco number required Preço. Example: 150.50
 * @bodyParam ativo boolean Status. Example: true
 * @bodyParam categorias array Lista de categorias. Example: ["fertilizantes", "npk"]
 */

Formato: @bodyParam nome tipo [required] descrição. Example: valor

Tipos suportados:

  • string
  • integer / int
  • number / float / double
  • boolean / bool
  • array
  • object
  • file

@response

Exemplo de resposta da API.

/**
 * @response 200 {
 *   "success": true,
 *   "data": {
 *     "id": 1,
 *     "nome": "Produto A"
 *   }
 * }
 *
 * @response 404 {
 *   "success": false,
 *   "message": "Recurso não encontrado"
 * }
 */

Múltiplas respostas:

/**
 * @response 200 scenario="Sucesso" {
 *   "success": true,
 *   "data": {...}
 * }
 *
 * @response 401 scenario="Não autenticado" {
 *   "message": "Unauthenticated"
 * }
 *
 * @response 422 scenario="Validação falhou" {
 *   "message": "The given data was invalid.",
 *   "errors": {...}
 * }
 */

Headers customizados para a requisição.

/**
 * @header X-Custom-Header valor
 * @header Accept-Language pt-BR
 */

@responseFile

Usar um arquivo JSON como resposta.

/**
 * @responseFile storage/responses/produtos.json
 * @responseFile 404 storage/responses/not-found.json
 */

Exemplos Práticos

Exemplo 1: Endpoint de Login (Não Autenticado)

/**
 * @group Autenticação
 *
 * APIs para autenticação de usuários
 */
class AuthController extends Controller
{
    /**
     * Login
     *
     * Realiza autenticação do usuário e retorna um token de acesso.
     *
     * @unauthenticated
     *
     * @bodyParam email string required Email do usuário. Example: produtor@agrsis.com.br
     * @bodyParam password string required Senha do usuário. Example: senha123
     *
     * @response 200 {
     *   "success": true,
     *   "message": "Login realizado com sucesso",
     *   "data": {
     *     "user": {
     *       "id": 1,
     *       "name": "João Silva",
     *       "email": "produtor@agrsis.com.br"
     *     },
     *     "token": "1|abcdefghijklmnopqrstuvwxyz"
     *   }
     * }
     *
     * @response 401 {
     *   "success": false,
     *   "message": "Credenciais inválidas"
     * }
     */
    public function login(Request $request)
    {
        // ...
    }
}

Exemplo 2: Endpoint CRUD (Autenticado)

/**
 * @group Produtos
 *
 * APIs para gerenciamento de produtos
 */
class ProdutoController extends Controller
{
    /**
     * Listar Produtos
     *
     * Retorna uma lista paginada de produtos.
     *
     * @authenticated
     *
     * @queryParam page integer Número da página. Example: 1
     * @queryParam per_page integer Itens por página. Example: 15
     * @queryParam search string Buscar no nome. Example: fertilizante
     *
     * @response 200 {
     *   "success": true,
     *   "data": {
     *     "current_page": 1,
     *     "data": [
     *       {
     *         "id": 1,
     *         "nome": "Fertilizante NPK 10-10-10",
     *         "preco": 150.50
     *       }
     *     ],
     *     "total": 50
     *   }
     * }
     */
    public function index(Request $request)
    {
        // ...
    }

    /**
     * Criar Produto
     *
     * Cria um novo produto no sistema.
     *
     * @authenticated
     *
     * @bodyParam nome string required Nome do produto. Example: Fertilizante NPK 20-05-20
     * @bodyParam descricao string Descrição do produto. Example: Fertilizante mineral misto
     * @bodyParam preco number required Preço. Example: 175.50
     *
     * @response 201 {
     *   "success": true,
     *   "message": "Produto criado com sucesso",
     *   "data": {
     *     "id": 3,
     *     "nome": "Fertilizante NPK 20-05-20",
     *     "preco": 175.50
     *   }
     * }
     *
     * @response 422 {
     *   "message": "The given data was invalid.",
     *   "errors": {
     *     "nome": ["O campo nome é obrigatório."]
     *   }
     * }
     */
    public function store(Request $request)
    {
        // ...
    }
}

Exemplo 3: Upload de Arquivo

/**
 * Upload de Imagem
 *
 * Faz upload de uma imagem do produto.
 *
 * @authenticated
 *
 * @urlParam id integer required ID do produto. Example: 1
 * @bodyParam imagem file required Arquivo de imagem (JPG, PNG). Example: /path/to/image.jpg
 *
 * @response 200 {
 *   "success": true,
 *   "message": "Imagem enviada com sucesso",
 *   "data": {
 *     "url": "https://exemplo.com/storage/produtos/imagem.jpg"
 *   }
 * }
 */
public function uploadImagem(Request $request, $id)
{
    // ...
}

Comandos Úteis

Gerar Documentação

# Local
php artisan scribe:generate

# Docker
docker exec agrsis_api php artisan scribe:generate

Limpar Cache da Documentação

# Local
rm -rf .scribe/endpoints.cache/*
php artisan scribe:generate

# Docker
docker exec agrsis_api rm -rf .scribe/endpoints.cache/*
docker exec agrsis_api php artisan scribe:generate

Publicar Configuração (já feito)

php artisan vendor:publish --tag=scribe-config

Atualizar Scribe

composer update knuckleswtf/scribe

Exportação para Outras Ferramentas

Importar no Postman

  1. Acesse: http://localhost:8000/docs.postman
  2. Copie o conteúdo JSON
  3. No Postman: ImportRaw text → Cole o JSON → ContinueImport

Ou baixe diretamente:

# Copiar collection para área de trabalho
cp storage/app/private/scribe/collection.json ~/Desktop/agrsis-api-postman.json

Importar no Insomnia

O Insomnia suporta OpenAPI:

  1. Acesse: http://localhost:8000/docs.openapi
  2. Copie o conteúdo YAML
  3. No Insomnia: CreateImport FromURL/File → Cole ou selecione arquivo

Ou baixe diretamente:

# Copiar OpenAPI spec para área de trabalho
cp storage/app/private/scribe/openapi.yaml ~/Desktop/agrsis-api-openapi.yaml

Swagger UI

Você pode usar o arquivo OpenAPI em qualquer Swagger UI:

# Exemplo com Docker
docker run -p 8080:8080 -e SWAGGER_JSON=/app/openapi.yaml \
  -v $(pwd)/storage/app/private/scribe/openapi.yaml:/app/openapi.yaml \
  swaggerapi/swagger-ui

Acesse: http://localhost:8080


Configuração Avançada

Arquivo de Configuração

O arquivo de configuração fica em: config/scribe.php

Principais Configurações

Título e Descrição

'title' => 'AgrSis API',
'description' => 'API da plataforma AgrSis - Sistema de Licitação Eletrônica',

URL Base

'base_url' => config('app.url'),
// Ou fixo: 'base_url' => 'https://api.agrsis.com.br',

Tipo de Documentação

'type' => 'laravel', // ou 'static'
  • laravel: Gera views Blade (recomendado)
  • static: Gera HTML estático em public/docs

Autenticação

'auth' => [
    'enabled' => true,
    'default' => true, // Todos endpoints autenticados por padrão
    'in' => 'bearer', // bearer, header, query, body
    'name' => 'Authorization',
    'placeholder' => '{SEU_TOKEN_SANCTUM}',
],

Linguagens de Exemplo

'example_languages' => [
    'bash',
    'javascript',
    'php',
    'python',
],

Rotas a Documentar

'routes' => [
    [
        'match' => [
            'prefixes' => ['api/*'], // Apenas rotas que começam com api/
        ],
        'exclude' => [
            // 'GET /health', // Exemplo de exclusão
        ],
    ],
],

Try It Out

'try_it_out' => [
    'enabled' => true,
    'base_url' => null, // null usa o base_url da config
    'use_csrf' => false, // true se usar Sanctum SPA
    'csrf_url' => '/sanctum/csrf-cookie',
],

Logo Customizado

// Em config/scribe.php
'logo' => 'img/logo.png', // Arquivo em public/img/logo.png

Grupos Customizados

'groups' => [
    'default' => 'Endpoints',
    'order' => [
        'Autenticação',
        'Produtos',
        'Cotações',
        'Pedidos',
    ],
],

Estrutura de Arquivos

api/
├── .scribe/                          # Cache e arquivos intermediários
│   ├── endpoints/                    # Endpoints processados
│   ├── endpoints.cache/              # Cache de endpoints
│   ├── auth.md                       # Texto de autenticação
│   └── intro.md                      # Texto de introdução
│
├── config/
│   └── scribe.php                    # Configuração do Scribe
│
├── resources/views/scribe/           # Views Blade da documentação
│
├── public/vendor/scribe/             # Assets (CSS, JS)
│
├── storage/app/private/scribe/
│   ├── collection.json               # Postman Collection
│   └── openapi.yaml                  # OpenAPI Spec
│
└── README_SCRIBE.md                  # Este arquivo

Boas Práticas

1. Sempre Gere Após Alterações

# Após modificar controllers
php artisan scribe:generate

2. Use Exemplos Realistas

/**
 * @bodyParam nome string required Nome do produto. Example: Fertilizante NPK 10-10-10
 */

Evite exemplos genéricos como "string", "123", etc.

3. Documente Todos os Cenários

/**
 * @response 200 scenario="Sucesso" {...}
 * @response 401 scenario="Não autenticado" {...}
 * @response 403 scenario="Sem permissão" {...}
 * @response 404 scenario="Não encontrado" {...}
 * @response 422 scenario="Validação falhou" {...}
 */

4. Agrupe Endpoints Logicamente

/**
 * @group Autenticação
 */

/**
 * @group Produtos
 * @subgroup Categorias
 */

5. Use Descrições Claras

/**
 * Listar Produtos Ativos
 *
 * Retorna uma lista paginada de produtos ativos no sistema,
 * com suporte a filtros e busca por nome ou categoria.
 */

6. Mantenha Sincronizado

  • Sempre que adicionar/remover endpoints, atualize a documentação
  • Revise a documentação periodicamente
  • Teste os exemplos para garantir que estão corretos

Troubleshooting

Problema: Endpoint não aparece na documentação

Solução:

  1. Verifique se a rota está em routes/api.php
  2. Confirme que o prefixo está em config/scribe.phproutes.match.prefixes
  3. Limpe o cache: rm -rf .scribe/endpoints.cache/*
  4. Gere novamente: php artisan scribe:generate

Problema: Try It Out não funciona

Solução:

  1. Verifique try_it_out.enabled em config/scribe.php
  2. Configure CORS se a API estiver em domínio diferente
  3. Verifique se a URL base está correta

Problema: Autenticação não funciona nos exemplos

Solução:

  1. Configure auth.enabled = true em config/scribe.php
  2. Verifique auth.in (deve ser 'bearer' para Sanctum)
  3. Use @authenticated nos métodos

Problema: Erro ao gerar documentação

Solução:

  1. Verifique sintaxe das anotações
  2. Execute: php artisan route:clear && php artisan config:clear
  3. Verifique logs: storage/logs/laravel.log


Conclusão

O Scribe torna a documentação da API uma tarefa simples e automatizada. Basta adicionar anotações nos controllers e gerar a documentação.

Checklist Rápido

  • Adicionar anotações @group na classe do controller
  • Adicionar anotações @authenticated ou @unauthenticated nos métodos
  • Documentar parâmetros com @urlParam, @queryParam, @bodyParam
  • Adicionar exemplos de resposta com @response
  • Gerar documentação: php artisan scribe:generate
  • Testar acessando http://localhost:8000/docs

Qualquer dúvida, consulte este README ou a documentação oficial!


Última atualização: 2025-12-04 Versão Scribe: 5.6.0 Versão Laravel: 11

Copyright © 2026