# API Documentation

> Swagger/OpenAPI setup and documentation patterns for SE104_VLEAGUE Use when this capability is needed.

- Skill: `tomevault-io/api-documentation-6` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/api-documentation-6`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/api-documentation-6/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/api-documentation-6

---


# API Documentation Skill

## Swagger Setup

Swagger UI available at `/api/docs` (set up in `main.ts`).

```typescript
const config = new DocumentBuilder()
  .setTitle('VLeague API')
  .setDescription('V-League Football Management System API')
  .setVersion('1.0')
  .addBearerAuth(
    {
      type: 'http',
      scheme: 'bearer',
      bearerFormat: 'JWT',
      name: 'JWT',
      description: 'Enter JWT access token',
      in: 'header',
    },
    'access-token',
  )
  .addTag('Authentication', 'User authentication endpoints')
  .addTag('Teams', 'Team management endpoints')
  .addTag('Players', 'Player management endpoints')
  .addTag('Matches', 'Match scheduling and management')
  .addTag('Scheduling', 'Schedule generation and publishing')
  .addTag('Seasons', 'Season management')
  .addTag('Stadiums', 'Stadium management')
  .addTag('Roster', 'Team roster management')
  .addTag('Regulations', 'Season regulations')
  .addTag('Standings', 'League standings & statistics')
  .addTag('Users', 'User management (ADMIN)')
  .addTag('Upload', 'File upload')
  .addTag('Search', 'Global search')
  .addTag('Health', 'Health check')
  .build();

const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('docs', app, document);
```

---

## Controller Documentation

```typescript
@ApiTags('Teams')
@Controller('teams')
export class TeamsController {
  @Get()
  @ApiOperation({ summary: 'List all teams' })
  @ApiResponse({ status: 200, description: 'Teams retrieved successfully' })
  @Public()
  findAll(@Query() query: PaginationQueryDto) {}

  @Post()
  @ApiOperation({ summary: 'Create a team' })
  @ApiResponse({ status: 201, description: 'Team created' })
  @ApiResponse({ status: 409, description: 'Team name already exists' })
  @ApiBearerAuth()
  @Roles(UserRole.ADMIN)
  create(@Body() dto: CreateTeamDto) {}
}
```

---

## DTO Documentation

```typescript
export class CreateTeamDto {
  @ApiProperty({ description: 'Team name', example: 'Hoàng Anh Gia Lai' })
  @IsString()
  @IsNotEmpty()
  name: string;

  @ApiPropertyOptional({ description: 'Short name', example: 'HAGL' })
  @IsOptional()
  @IsString()
  shortName?: string;

  @ApiPropertyOptional({ description: 'City', example: 'Pleiku' })
  @IsOptional()
  @IsString()
  city?: string;

  @ApiPropertyOptional({ enum: TeamStatus, default: TeamStatus.ACTIVE })
  @IsOptional()
  @IsEnum(TeamStatus)
  status?: TeamStatus;
}
```

---

## Error Response Shape

All API errors follow this schema:

```json
{
  "statusCode": 400,
  "code": "VALIDATION_ERROR",
  "message": "Validation failed",
  "details": ["field must be a string"],
  "requestId": "uuid",
  "timestamp": "2026-01-01T00:00:00.000Z"
}
```

---

## Decorator Reference

| Decorator                                | Purpose                |
| ---------------------------------------- | ---------------------- |
| `@ApiTags('Tag')`                        | Group endpoints by tag |
| `@ApiOperation({ summary })`             | Endpoint description   |
| `@ApiResponse({ status, description })`  | Response documentation |
| `@ApiBearerAuth()`                       | Mark as JWT-protected  |
| `@ApiProperty({ description, example })` | Required field         |
| `@ApiPropertyOptional({...})`            | Optional field         |
| `@ApiQuery({ name, required, enum })`    | Query parameter        |
| `@ApiParam({ name, description })`       | Path parameter         |
| `@ApiConsumes('multipart/form-data')`    | File upload endpoint   |

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/daithang-organization) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-13 -->

