Marketplace

api-portal-design

API documentation and developer portal design

allowed_tools: Read, Glob, Grep, Write, Edit

$ Installieren

git clone https://github.com/melodic-software/claude-code-plugins /tmp/claude-code-plugins && cp -r /tmp/claude-code-plugins/plugins/documentation-standards/skills/api-portal-design ~/.claude/skills/claude-code-plugins

// tip: Run this command in your terminal to install the skill


name: api-portal-design description: API documentation and developer portal design allowed-tools: Read, Glob, Grep, Write, Edit

API Portal Design Skill

When to Use This Skill

Use this skill when:

  • Api Portal Design tasks - Working on api documentation and developer portal design
  • Planning or design - Need guidance on Api Portal Design approaches
  • Best practices - Want to follow established patterns and standards

Overview

Design comprehensive API documentation and developer portals for exceptional developer experience.

MANDATORY: Documentation-First Approach

Before designing API portals:

  1. Invoke docs-management skill for API documentation patterns
  2. Verify OpenAPI/AsyncAPI standards via MCP servers (context7)
  3. Base guidance on industry API documentation best practices

Developer Portal Architecture

Developer Portal Components:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                           Developer Portal                                   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”‚
โ”‚  โ”‚  Getting    โ”‚  โ”‚    API      โ”‚  โ”‚   Code      โ”‚  โ”‚   API       โ”‚        โ”‚
โ”‚  โ”‚  Started    โ”‚  โ”‚  Reference  โ”‚  โ”‚  Examples   โ”‚  โ”‚  Console    โ”‚        โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”‚
โ”‚  โ”‚   SDKs &    โ”‚  โ”‚  Change     โ”‚  โ”‚   Status    โ”‚  โ”‚   Support   โ”‚        โ”‚
โ”‚  โ”‚  Libraries  โ”‚  โ”‚    Log      โ”‚  โ”‚    Page     โ”‚  โ”‚   Center    โ”‚        โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚                    Authentication & API Keys                         โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Portal Content Structure

Essential Sections

SectionPurposePriority
Getting StartedFirst-time user guideP0
AuthenticationHow to authenticateP0
API ReferenceComplete endpoint docsP0
Code ExamplesCopy-paste samplesP0
SDKsClient librariesP1
ChangelogVersion historyP1
Rate LimitsUsage constraintsP1
ErrorsError handling guideP1
WebhooksEvent notificationsP2
Best PracticesUsage recommendationsP2

Getting Started Guide

# Getting Started

Get up and running with the [Product] API in 5 minutes.

## Prerequisites

- An account on [Product] ([Sign up free](link))
- An API key ([Get your key](link))
- Basic knowledge of REST APIs

## Quick Start

### 1. Get Your API Key

1. Log in to your [Product] dashboard
2. Navigate to **Settings โ†’ API Keys**
3. Click **Create New Key**
4. Copy your key (you won't see it again!)

### 2. Make Your First Request

```bash
curl -X GET "https://api.example.com/v1/users/me" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

{
  "id": "usr_123abc",
  "email": "developer@example.com",
  "name": "Jane Developer",
  "created_at": "2025-01-15T10:30:00Z"
}

3. Explore the API

Next Steps

GoalResource
Understand authenticationAuthentication Guide
Browse all endpointsAPI Reference
Handle errors gracefullyError Handling
Go to productionProduction Checklist

Need Help?

Authentication Documentation

# Authentication

All API requests require authentication using Bearer tokens.

## API Keys

API keys are long-lived credentials for server-to-server communication.

### Creating API Keys

1. Go to **Dashboard โ†’ Settings โ†’ API Keys**
2. Click **Create New Key**
3. Give it a descriptive name
4. Select the appropriate permissions
5. Copy and securely store the key

### Using API Keys

Include your API key in the `Authorization` header:

```bash
curl -X GET "https://api.example.com/v1/resource" \
  -H "Authorization: Bearer YOUR_API_KEY"

Key Security Best Practices

DoDon't
Store keys in environment variablesCommit keys to source control
Use separate keys per environmentShare keys between services
Rotate keys regularlyUse keys in client-side code
Set minimum required permissionsUse admin keys for all operations

OAuth 2.0

For user-facing applications, use OAuth 2.0 for secure delegated access.

Authorization Code Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Client  โ”‚                               โ”‚   Auth   โ”‚
โ”‚   App    โ”‚                               โ”‚  Server  โ”‚
โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜                               โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜
     โ”‚                                          โ”‚
     โ”‚ 1. Redirect to authorization endpoint    โ”‚
     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บโ”‚
     โ”‚                                          โ”‚
     โ”‚ 2. User authenticates and consents       โ”‚
     โ”‚                                          โ”‚
     โ”‚ 3. Redirect back with authorization code โ”‚
     โ”‚โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
     โ”‚                                          โ”‚
     โ”‚ 4. Exchange code for tokens              โ”‚
     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บโ”‚
     โ”‚                                          โ”‚
     โ”‚ 5. Return access_token and refresh_token โ”‚
     โ”‚โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
     โ”‚                                          โ”‚

OAuth Endpoints

EndpointURL
Authorizationhttps://auth.example.com/oauth/authorize
Tokenhttps://auth.example.com/oauth/token
Revokehttps://auth.example.com/oauth/revoke

Scopes

ScopeDescription
read:usersRead user information
write:usersCreate and update users
read:ordersRead order data
write:ordersCreate and modify orders

Token Refresh

curl -X POST "https://auth.example.com/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=YOUR_REFRESH_TOKEN" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

OpenAPI Specification Template

openapi: 3.1.0
info:
  title: Product API
  version: 1.0.0
  description: |
    The Product API provides programmatic access to [Product] features.

    ## Authentication

    All endpoints require authentication via Bearer token.
    Get your API key from the [Dashboard](https://dashboard.example.com).

    ## Rate Limiting

    - Standard: 100 requests/minute
    - Premium: 1000 requests/minute

    See [Rate Limits](/docs/rate-limits) for details.

  contact:
    name: API Support
    email: api-support@example.com
    url: https://example.com/support
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://api.example.com/v1
    description: Production
  - url: https://api-staging.example.com/v1
    description: Staging

security:
  - bearerAuth: []

tags:
  - name: Users
    description: User management operations
  - name: Orders
    description: Order processing operations

paths:
  /users:
    get:
      tags: [Users]
      operationId: listUsers
      summary: List all users
      description: |
        Returns a paginated list of users in your organization.

        Results are sorted by creation date, newest first.
      parameters:
        - name: limit
          in: query
          description: Maximum number of results to return
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - name: cursor
          in: query
          description: Pagination cursor from previous response
          schema:
            type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserList'
              examples:
                default:
                  summary: Example response
                  value:
                    data:
                      - id: "usr_123"
                        email: "jane@example.com"
                        name: "Jane Doe"
                        created_at: "2025-01-15T10:30:00Z"
                    has_more: true
                    next_cursor: "cur_abc123"
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'

    post:
      tags: [Users]
      operationId: createUser
      summary: Create a user
      description: Creates a new user in your organization.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
            examples:
              basic:
                summary: Basic user creation
                value:
                  email: "jane@example.com"
                  name: "Jane Doe"
              with_metadata:
                summary: User with metadata
                value:
                  email: "jane@example.com"
                  name: "Jane Doe"
                  metadata:
                    department: "Engineering"
                    role: "Developer"
      responses:
        '201':
          description: User created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          description: User already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /users/{userId}:
    get:
      tags: [Users]
      operationId: getUser
      summary: Get a user
      description: Retrieves a user by their ID.
      parameters:
        - name: userId
          in: path
          required: true
          description: The user's unique identifier
          schema:
            type: string
            pattern: '^usr_[a-zA-Z0-9]+$'
          example: usr_123abc
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          $ref: '#/components/responses/NotFound'

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        Use your API key as the Bearer token.

        Example: `Authorization: Bearer sk_live_abc123`

  schemas:
    User:
      type: object
      required: [id, email, created_at]
      properties:
        id:
          type: string
          description: Unique identifier for the user
          example: usr_123abc
        email:
          type: string
          format: email
          description: User's email address
          example: jane@example.com
        name:
          type: string
          description: User's display name
          example: Jane Doe
        created_at:
          type: string
          format: date-time
          description: When the user was created
          example: "2025-01-15T10:30:00Z"
        metadata:
          type: object
          additionalProperties: true
          description: Custom key-value pairs

    UserList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
        has_more:
          type: boolean
          description: Whether more results are available
        next_cursor:
          type: string
          description: Cursor for fetching next page

    CreateUserRequest:
      type: object
      required: [email]
      properties:
        email:
          type: string
          format: email
        name:
          type: string
        metadata:
          type: object
          additionalProperties: true

    Error:
      type: object
      required: [error]
      properties:
        error:
          type: object
          required: [code, message]
          properties:
            code:
              type: string
              description: Error code
              example: invalid_request
            message:
              type: string
              description: Human-readable error message
              example: The email field is required
            details:
              type: array
              items:
                type: object
                properties:
                  field:
                    type: string
                  message:
                    type: string

  responses:
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: invalid_request
              message: Validation failed
              details:
                - field: email
                  message: Invalid email format

    Unauthorized:
      description: Authentication required
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: unauthorized
              message: Invalid or missing API key

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: not_found
              message: User not found

    RateLimited:
      description: Rate limit exceeded
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
          description: Request limit per minute
        X-RateLimit-Remaining:
          schema:
            type: integer
          description: Remaining requests in current window
        X-RateLimit-Reset:
          schema:
            type: integer
          description: Unix timestamp when limit resets
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: rate_limited
              message: Too many requests. Please retry after 60 seconds.

Error Documentation

# Error Handling

The API uses conventional HTTP response codes and returns detailed error information.

## HTTP Status Codes

| Code | Meaning |
|------|---------|
| 200 | Success |
| 201 | Created |
| 204 | No Content |
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Invalid or missing credentials |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Resource doesn't exist |
| 409 | Conflict - Resource already exists |
| 422 | Unprocessable - Validation failed |
| 429 | Too Many Requests - Rate limited |
| 500 | Internal Error - Server-side issue |

## Error Response Format

```json
{
  "error": {
    "code": "invalid_request",
    "message": "The email field is required",
    "request_id": "req_abc123",
    "details": [
      {
        "field": "email",
        "message": "This field is required"
      }
    ]
  }
}

Error Codes Reference

Authentication Errors

CodeDescriptionResolution
unauthorizedMissing or invalid API keyCheck your API key is correct
token_expiredAccess token has expiredRefresh your token
insufficient_scopeToken lacks required scopeRequest additional scopes

Validation Errors

CodeDescriptionResolution
invalid_requestRequest body is malformedCheck JSON syntax
validation_failedOne or more fields invalidSee details array
missing_required_fieldRequired field not providedInclude all required fields

Resource Errors

CodeDescriptionResolution
not_foundResource doesn't existVerify the ID is correct
already_existsResource already existsUse existing resource or change identifier
resource_lockedResource is being modifiedRetry after a short delay

Handling Errors in Code

csharp

try
{
    var user = await client.Users.GetAsync(userId, ct);
}
catch (ApiException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
    _logger.LogWarning("User {UserId} not found", userId);
    return NotFound();
}
catch (ApiException ex) when (ex.StatusCode == HttpStatusCode.TooManyRequests)
{
    var retryAfter = ex.Headers.RetryAfter?.Delta ?? TimeSpan.FromSeconds(60);
    await Task.Delay(retryAfter, ct);
    // Retry request
}
catch (ApiException ex)
{
    _logger.LogError(ex, "API error: {Code} - {Message}", ex.Error.Code, ex.Error.Message);
    throw;
}

TypeScript

try {
  const user = await client.users.get(userId);
} catch (error) {
  if (error instanceof ApiError) {
    switch (error.code) {
      case 'not_found':
        console.warn(`User ${userId} not found`);
        return null;
      case 'rate_limited':
        await sleep(error.retryAfter ?? 60000);
        return client.users.get(userId); // Retry
      default:
        console.error(`API error: ${error.code} - ${error.message}`);
        throw error;
    }
  }
  throw error;
}

Code Examples Section

# Code Examples

Ready-to-use examples in popular languages.

## Create a User

### cURL

```bash
curl -X POST "https://api.example.com/v1/users" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@example.com",
    "name": "Jane Doe"
  }'

C# (.NET)

using var client = new ProductApiClient(apiKey);

var user = await client.Users.CreateAsync(new CreateUserRequest
{
    Email = "jane@example.com",
    Name = "Jane Doe"
});

Console.WriteLine($"Created user: {user.Id}");

TypeScript

import { ProductApi } from '@example/sdk';

const client = new ProductApi({ apiKey: process.env.API_KEY });

const user = await client.users.create({
  email: 'jane@example.com',
  name: 'Jane Doe',
});

console.log(`Created user: ${user.id}`);

Python

from example_sdk import ProductApi

client = ProductApi(api_key=os.environ["API_KEY"])

user = client.users.create(
    email="jane@example.com",
    name="Jane Doe"
)

print(f"Created user: {user.id}")

Portal Tooling Options

ToolTypeBest For
StoplightHostedDesign-first, collaboration
RedoclyHosted/SelfOpenAPI rendering
ReadMeHostedFull portal, interactive
SwaggerHubHostedSwagger ecosystem
ScalarOpen SourceModern, customizable
Docusaurus + PluginOpen SourceFull control

Best Practices

Developer Experience Principles

PrincipleImplementation
Time to First CallMinimize steps to make first API call
Copy-Paste ReadyAll examples should work immediately
Error MessagesClear, actionable error responses
ConsistencySame patterns across all endpoints
DiscoverabilityEasy to find and navigate

Documentation Quality Checklist

  • Every endpoint has description and examples
  • All parameters documented with types and constraints
  • Response schemas fully documented
  • Error codes explained with resolutions
  • Authentication clearly explained
  • Rate limits documented
  • Code examples in multiple languages
  • Getting started guide under 5 minutes

Workflow

When designing API portals:

  1. Define Audience: Who will use the API?
  2. Structure Content: Organize by user journey
  3. Write OpenAPI Spec: Complete specification
  4. Add Examples: Working code in target languages
  5. Build Portal: Choose tooling, implement
  6. Test with Users: Validate time-to-first-call
  7. Iterate: Improve based on feedback

References

For detailed guidance:


Last Updated: 2025-12-26

Repository

melodic-software
melodic-software
Author
melodic-software/claude-code-plugins/plugins/documentation-standards/skills/api-portal-design
3
Stars
0
Forks
Updated4d ago
Added1w ago