# API Documentation

This page covers standards for documenting APIs using OpenAPI specifications across all Decentraland services.

## Goals

Our API documentation approach ensures:

* **Standardization** - Consistent OpenAPI specs across all services
* **Automation** - Validation, bundling, and deployment via GitHub Actions
* **Centralization** - All service documentation published through GitBook
* **Ownership** - Documentation lives with each service repository
* **Accessibility** - Contributor-friendly, up-to-date API references

***

## Repository Structure

Each service repository MUST include a `/docs` directory with the following structure:

```bash
/docs
  openapi.yaml        # Source of truth (OpenAPI 3.1)
  openapi.json        # Auto-generated in CI for Hugo/renderers
  index.html          # Auto-generated standalone docs (optional)
```

### File Requirements

#### `openapi.yaml`

* **MUST** be the canonical source file
* **MUST** use OpenAPI 3.1 specification
* **MAY** have a service-identifying prefix (e.g., `worlds-openapi.yaml`)
* **MAY** split into `components/` or `examples/` directories if needed

#### `openapi.json`

* Auto-generated during CI/CD
* Used by Hugo and other renderers
* Do not edit manually

#### `index.html`

* Auto-generated standalone documentation
* Built using Redocly
* Deployed to GitHub Pages

***

## OpenAPI Standards

When writing `openapi.yaml`, follow these conventions to ensure consistency and clarity.

### Endpoint Summary

**MUST** reflect the actual endpoint path:

```yaml
# ✅ Good: Clear endpoint path
paths:
  /world/{world_name}/about:
    get:
      summary: /world/{world_name}/about
      description: Retrieves information about a specific world
      
# ❌ Bad: Generic summary
paths:
  /world/{world_name}/about:
    get:
      summary: Get world info
```

### Operation ID

**MUST** include the service name for global uniqueness:

```yaml
# ✅ Good: Service-prefixed operation ID
operationId: worldsContentServer_getWorldAbout

# ✅ Good: Another example
operationId: socialService_getFriends

# ❌ Bad: Generic, could conflict
operationId: getAbout
```

**Naming convention**: `{serviceName}_{operationDescription}`

* Use camelCase
* Be descriptive but concise
* Include HTTP method context when helpful (e.g., `createUser`, `deleteParcel`)

### Versioning

**MUST** use semantic versioning (`MAJOR.MINOR.PATCH`) in `info.version`:

```yaml
openapi: 3.1.0
info:
  title: Worlds Content Server API
  version: 1.2.0  # Semantic versioning
  description: API for managing Decentraland worlds
```

**Version bumping rules**:

* **MAJOR**: Breaking changes (incompatible API changes)
* **MINOR**: New functionality (backward-compatible)
* **PATCH**: Bug fixes (backward-compatible)

### Tags and Grouping

**MUST** use tags to group related endpoints:

```yaml
tags:
  - name: Worlds
    description: World management operations
  - name: Deployments
    description: World deployment operations
  - name: Health
    description: Health check endpoints

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" %}
Operations are grouped by tag in GitBook's navigation. Group related endpoints under the same tag for better organization.
{% endhint %}

### Complete Example

```yaml
openapi: 3.1.0
info:
  title: Social Service API
  version: 2.1.0
  description: API for managing social interactions in Decentraland
  contact:
    name: Decentraland Contributors
    url: https://decentraland.org

servers:
  - url: https://social.decentraland.org
    description: Production server
  - url: https://social.decentraland.zone
    description: Staging server

tags:
  - name: Friends
    description: Friend management
  - name: Blocked Users
    description: User blocking operations

paths:
  /friends:
    get:
      tags:
        - Friends
      summary: /friends
      operationId: socialService_getFriends
      description: Returns a list of the authenticated user's friends
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  friends:
                    type: array
                    items:
                      $ref: '#/components/schemas/Friend'
        '401':
          description: Unauthorized

components:
  schemas:
    Friend:
      type: object
      required:
        - address
        - createdAt
      properties:
        address:
          type: string
          description: Ethereum address of the friend
        createdAt:
          type: string
          format: date-time
          description: When the friendship was established
```

***

## Local Development

### Preview Documentation Locally

Use Redocly CLI to preview your OpenAPI documentation:

```bash
# Build HTML documentation
yarn redocly build-docs docs/openapi.yaml -o docs/index.html

# Then open docs/index.html in your browser
```

### Add to package.json

Add a build script for convenience:

```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"
  }
}
```

### Install Redocly CLI

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

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

### Validate OpenAPI Spec

```bash
# Validate your spec
redocly lint docs/openapi.yaml

# Bundle and validate
redocly bundle docs/openapi.yaml
```

***

## Automation Setup

### Step 1: Configure GitBook Secrets

To publish API specs to GitBook, add these secrets to your repository:

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

| Secret Name               | Description                  | Where to Find                   |
| ------------------------- | ---------------------------- | ------------------------------- |
| `GITBOOK_ORGANIZATION_ID` | Your GitBook organization ID | GitBook Settings → Organization |
| `GITBOOK_TOKEN`           | GitBook API token            | GitBook Settings → API Tokens   |

{% hint style="warning" %}
These secrets MUST be configured for the automated workflow to publish to GitBook.
{% endhint %}

### Step 2: Add GitHub Actions Workflow

Create `.github/workflows/build-api-docs.yml` in your repository:

```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'  # e.g., 'social-service-api'
      node-version: '20'
    secrets: inherit
```

**Parameters**:

* `api-spec-file`: Path to your OpenAPI spec (usually `docs/openapi.yaml`)
* `output-file`: Where to generate HTML docs
* `output-directory`: Directory for output files
* `api-spec-name`: Unique name for your API spec (used in GitBook)
* `node-version`: Node.js version to use

**This workflow will**:

1. ✅ Validate the OpenAPI spec
2. ✅ Bundle the spec into a single file
3. ✅ Build static HTML documentation using Redocly
4. ✅ Deploy automatically to GitHub Pages
5. ✅ Publish spec to GitBook (if secrets are configured)

### Step 3: Enable GitHub Pages

Configure GitHub Pages in your repository:

1. Go to **Settings → Pages**
2. Under **Build and deployment**:
   * Set **Source** to **GitHub Actions**
3. Ensure there is an environment named **github-pages**
4. Save settings

After the first successful workflow run, your documentation will be available at:

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

{% hint style="success" %}
These URLs remain valid as long as the repository exists and GitHub Pages is enabled.
{% endhint %}

***

## Adding to GitBook

Once your API documentation is deployed, add it to the centralized GitBook documentation.

### Manual Addition (Current Process)

1. Navigate to the GitBook space
2. Go to the **API Reference** section
3. Click **Add API Reference**
4. Enter your service details:
   * **Name**: Your service name (e.g., "Social Service")
   * **OpenAPI URL**: `https://decentraland.github.io/{repo-name}/openapi.yaml`
5. Save

### GitBook Integration Features

GitBook will automatically:

* Parse your OpenAPI spec
* Generate interactive API documentation
* Create endpoint navigation based on tags
* Provide "Try it" functionality
* Keep docs in sync when you update the spec

***

## Complete Setup Flow

### Initial Setup

{% @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]" %}

### Ongoing Updates

{% @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]" %}

***

## Best Practices

### Documentation Quality

* **Be descriptive**: Write clear summaries and descriptions
* **Provide examples**: Include request/response examples
* **Document errors**: Describe all possible error responses
* **Use components**: Reuse schemas via `$ref` to avoid duplication
* **Add descriptions**: Every parameter, property, and response should have a description

### Example with Best Practices

```yaml
paths:
  /users/{address}/friends:
    get:
      tags:
        - Friends
      summary: /users/{address}/friends
      operationId: socialService_getUserFriends
      description: |
        Retrieves a paginated list of friends for the specified user.
        Returns friend addresses and metadata including when the friendship was established.
      parameters:
        - name: address
          in: path
          required: true
          description: Ethereum address of the user (0x-prefixed)
          schema:
            type: string
            pattern: '^0x[a-fA-F0-9]{40}$'
          example: '0x1234567890abcdef1234567890abcdef12345678'
        - name: limit
          in: query
          description: Maximum number of friends to return (1-100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
        - name: offset
          in: query
          description: Number of friends to skip for pagination
          schema:
            type: integer
            minimum: 0
            default: 0
      responses:
        '200':
          description: Successfully retrieved friends list
          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: Invalid address format
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: 'Invalid address format'
                code: 'INVALID_ADDRESS'
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
```

### Schema Reusability

```yaml
components:
  schemas:
    Error:
      type: object
      required:
        - error
        - code
      properties:
        error:
          type: string
          description: Human-readable error message
        code:
          type: string
          description: Machine-readable error code
        details:
          type: object
          description: Additional error context
          
    PaginatedResponse:
      type: object
      required:
        - offset
        - limit
        - total
      properties:
        offset:
          type: integer
          description: Number of items skipped
        limit:
          type: integer
          description: Maximum items per page
        total:
          type: integer
          description: Total number of items available
```

### Security Schemas

```yaml
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT token obtained from authentication endpoint

security:
  - BearerAuth: []
```

***

## Validation and Quality Checks

### Pre-Commit Validation

Add a pre-commit hook or CI check:

```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
```

### Common Validation Rules

* All paths have operation IDs
* All operations have tags
* All parameters have descriptions
* All responses are documented
* Examples are provided
* Schemas are properly referenced

***

## Troubleshooting

### Workflow Fails

**Problem**: GitHub Actions workflow fails

**Solutions**:

* Check workflow logs for validation errors
* Run `redocly lint docs/openapi.yaml` locally
* Verify file paths in workflow configuration
* Ensure secrets are properly configured

### GitHub Pages Not Working

**Problem**: Docs not appearing at GitHub Pages URL

**Solutions**:

* Verify GitHub Pages is enabled in repository settings
* Check that workflow completed successfully
* Wait a few minutes for GitHub Pages to update
* Verify the `github-pages` environment exists

### GitBook Not Syncing

**Problem**: GitBook not showing updated API docs

**Solutions**:

* Verify GitBook secrets are correct
* Check that the OpenAPI URL is accessible
* Manually trigger a refresh in GitBook
* Verify OpenAPI spec is valid

***

## Migration from Existing Docs

If you have existing API documentation:

1. **Export to OpenAPI**: Convert existing docs to OpenAPI 3.1 format
2. **Validate**: Use `redocly lint` to ensure compliance
3. **Add workflow**: Set up GitHub Actions automation
4. **Test**: Verify docs build and deploy correctly
5. **Update links**: Point old documentation links to new GitHub Pages URL
6. **Archive old docs**: Keep old docs for reference during transition

***

## Next Steps

* Review the [Well-Known Components](https://github.com/decentraland/docs/blob/main/contributor/contributor-guides/well-known-components/README.md) standards for API implementation
* See [Testing Standards](/contributor/contributor-guides/testing-standards.md) for API testing guidelines
* Check out existing API examples in the [API Reference](https://docs.decentraland.org) section

## Related Standards

* [Dependency Management](/contributor/contributor-guides/dependency-management.md) - Managing npm dependencies and peerDependencies
* [Well-Known Components](https://github.com/decentraland/docs/blob/main/contributor/contributor-guides/well-known-components/README.md) - WKC architecture for services
* [Testing Standards](/contributor/contributor-guides/testing-standards.md) - Testing patterns for services

## Resources

* **OpenAPI Specification**: [spec.openapis.org](https://spec.openapis.org/oas/latest.html)
* **Redocly CLI**: [redocly.com/docs/cli](https://redocly.com/docs/cli/)
* **GitBook API Integration**: [docs.gitbook.com](https://docs.gitbook.com)
* **Platform Actions Repo**: [github.com/decentraland/platform-actions](https://github.com/decentraland/platform-actions)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.decentraland.org/contributor/contributor-guides/api-documentation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
