Claude
Skills
Sign in
โ† Back

api.validate

Included with Lifetime
$97 forever

# api.validate

Backend & APIs

What this skill does

# api.validate

## Overview

**api.validate** validates OpenAPI and AsyncAPI specifications against enterprise guidelines, with built-in support for Zalando RESTful API Guidelines.

## Purpose

Ensure API specifications meet enterprise standards:
- Validate OpenAPI 3.x specifications
- Validate AsyncAPI 3.x specifications
- Check compliance with Zalando guidelines
- Detect common API design mistakes
- Provide actionable suggestions for fixes

## Usage

### Basic Usage

```bash
python skills/api.validate/api_validate.py <spec_path> [guideline_set] [options]
```

### Parameters

| Parameter | Required | Description | Default |
|-----------|----------|-------------|---------|
| `spec_path` | Yes | Path to API spec file | - |
| `guideline_set` | No | Guidelines to validate against | `zalando` |
| `--strict` | No | Warnings become errors | `false` |
| `--format` | No | Output format (json, human) | `json` |

### Guideline Sets

| Guideline | Status | Description |
|-----------|--------|-------------|
| `zalando` | โœ… Supported | Zalando RESTful API Guidelines |
| `google` | ๐Ÿšง Planned | Google API Design Guide |
| `microsoft` | ๐Ÿšง Planned | Microsoft REST API Guidelines |

## Examples

### Example 1: Validate OpenAPI Spec

```bash
python skills/api.validate/api_validate.py specs/user-service.openapi.yaml zalando
```

**Output** (JSON format):
```json
{
  "status": "success",
  "data": {
    "valid": false,
    "errors": [
      {
        "rule_id": "MUST_001",
        "message": "Missing required field 'info.x-api-id'",
        "severity": "error",
        "path": "info.x-api-id",
        "suggestion": "Add a UUID to uniquely identify this API"
      }
    ],
    "warnings": [
      {
        "rule_id": "SHOULD_001",
        "message": "Missing 'info.contact'",
        "severity": "warning",
        "path": "info.contact"
      }
    ],
    "spec_path": "specs/user-service.openapi.yaml",
    "spec_type": "openapi",
    "guideline_set": "zalando"
  }
}
```

### Example 2: Human-Readable Output

```bash
python skills/api.validate/api_validate.py \
  specs/user-service.openapi.yaml \
  zalando \
  --format=human
```

**Output**:
```
============================================================
API Validation Report
============================================================
Spec: specs/user-service.openapi.yaml
Type: OPENAPI
Guidelines: zalando
============================================================

โŒ ERRORS (1):
  [MUST_001] Missing required field 'info.x-api-id'
    Path: info.x-api-id
    ๐Ÿ’ก Add a UUID to uniquely identify this API

โš ๏ธ  WARNINGS (1):
  [SHOULD_001] Missing 'info.contact'
    Path: info.contact
    ๐Ÿ’ก Add contact information

============================================================
โŒ Validation FAILED
============================================================
```

### Example 3: Strict Mode

```bash
python skills/api.validate/api_validate.py \
  specs/user-service.openapi.yaml \
  zalando \
  --strict
```

In strict mode, warnings are treated as errors. Use for CI/CD pipelines where you want zero tolerance for issues.

### Example 4: Validate AsyncAPI Spec

```bash
python skills/api.validate/api_validate.py specs/user-events.asyncapi.yaml
```

## Validation Rules

### Zalando Guidelines (OpenAPI)

#### MUST Rules (Errors)

| Rule | Description | Example Fix |
|------|-------------|-------------|
| **MUST_001** | Required `x-api-id` metadata | `x-api-id: 'd0184f38-b98d-11e7-9c56-68f728c1ba70'` |
| **MUST_002** | Required `x-audience` metadata | `x-audience: 'company-internal'` |
| **MUST_003** | Path naming conventions | Use lowercase kebab-case or snake_case |
| **MUST_004** | Property naming (snake_case) | `userId` โ†’ `user_id` |
| **MUST_005** | HTTP method usage | GET should not have requestBody |

#### SHOULD Rules (Warnings)

| Rule | Description | Example Fix |
|------|-------------|-------------|
| **SHOULD_001** | Contact information | Add `info.contact` with team details |
| **SHOULD_002** | POST returns 201 | Add 201 response to POST operations |
| **SHOULD_003** | Document 400 errors | Add 400 Bad Request response |
| **SHOULD_004** | Document 500 errors | Add 500 Internal Error response |
| **SHOULD_005** | 201 includes Location header | Add Location header to 201 responses |
| **SHOULD_006** | Problem schema for errors | Define RFC 7807 Problem schema |
| **SHOULD_007** | Error responses use application/problem+json | Use correct content type |
| **SHOULD_008** | X-Flow-ID header | Add request tracing header |
| **SHOULD_009** | Security schemes defined | Add authentication schemes |

### AsyncAPI Guidelines

| Rule | Description |
|------|-------------|
| **ASYNCAPI_001** | Required `info` field |
| **ASYNCAPI_002** | Required `channels` field |
| **ASYNCAPI_003** | Version check (recommend 3.x) |

## Integration with Hooks

### Automatic Validation on File Edit

```bash
# Create hook using hook.define
python skills/hook.define/hook_define.py \
  on_file_edit \
  "python betty/skills/api.validate/api_validate.py {file_path} zalando" \
  --pattern="*.openapi.yaml" \
  --blocking=true \
  --timeout=10000 \
  --description="Validate OpenAPI specs on edit"
```

**Result**: Every time you edit a `*.openapi.yaml` file, it's automatically validated. If validation fails, the edit is blocked.

### Validation on Commit

```bash
python skills/hook.define/hook_define.py \
  on_commit \
  "python betty/skills/api.validate/api_validate.py {file_path} zalando --strict" \
  --pattern="specs/**/*.yaml" \
  --blocking=true \
  --description="Prevent commits with invalid specs"
```

## Exit Codes

| Code | Meaning |
|------|---------|
| `0` | Validation passed (no errors) |
| `1` | Validation failed (has errors) or execution error |

## Common Validation Errors

### Missing x-api-id

**Error**:
```
Missing required field 'info.x-api-id'
```

**Fix**:
```yaml
info:
  title: My API
  version: 1.0.0
  x-api-id: d0184f38-b98d-11e7-9c56-68f728c1ba70  # Add this
```

### Wrong Property Naming

**Error**:
```
Property 'userId' should use snake_case
```

**Fix**:
```yaml
# Before
properties:
  userId:
    type: string

# After
properties:
  user_id:
    type: string
```

### Missing Error Responses

**Error**:
```
GET operation should document 400 (Bad Request) response
```

**Fix**:
```yaml
responses:
  '200':
    description: Success
  '400':  # Add this
    $ref: '#/components/responses/BadRequest'
  '500':  # Add this
    $ref: '#/components/responses/InternalError'
```

### Wrong Content Type for Errors

**Error**:
```
Error response 400 should use 'application/problem+json'
```

**Fix**:
```yaml
'400':
  description: Bad request
  content:
    application/problem+json:  # Not application/json
      schema:
        $ref: '#/components/schemas/Problem'
```

## Use in Workflows

```yaml
# workflows/api_validation_suite.yaml
steps:
  - skill: api.validate
    args:
      - "specs/user-service.openapi.yaml"
      - "zalando"
      - "--strict"
    required: true
```

## Dependencies

- **PyYAML**: Required for YAML parsing
  ```bash
  pip install pyyaml
  ```

## Files

### Input
- `*.openapi.yaml` - OpenAPI 3.x specifications
- `*.asyncapi.yaml` - AsyncAPI 3.x specifications
- `*.json` - JSON format specifications

### Output
- JSON validation report (stdout)
- Human-readable report (with `--format=human`)

## See Also

- [hook.define](../hook.define/SKILL.md) - Create validation hooks
- [api.define](../api.define/SKILL.md) - Create OpenAPI specs
- [Betty Architecture](../../docs/betty-architecture.md) - Five-layer model
- [API-Driven Development](../../docs/api-driven-development.md) - Complete guide
- [Zalando API Guidelines](https://opensource.zalando.com/restful-api-guidelines/)
- [RFC 7807 Problem Details](https://datatracker.ietf.org/doc/html/rfc7807)

## Version

**0.1.0** - Initial implementation with Zalando guidelines support
Files: 6
Size: 32.5 KB
Complexity: 37/100
Category: Backend & APIs

Related in Backend & APIs