--- name: bunjs-apidog version: 1.0.0 description: Use when creating OpenAPI specs for Bun.js APIs, integrating with Apidog, documenting endpoints with schemas, or automating API specification imports via Apidog REST API. See bunjs for basics. keywords: - OpenAPI - Apidog - API documentation - Swagger - API specs - integration - API design plugin: dev updated: 2026-01-20 --- # Bun.js OpenAPI and Apidog Integration ## Overview This skill covers OpenAPI specification creation and Apidog integration for Bun.js TypeScript backend applications. Learn how to document APIs with OpenAPI 3.0, use Apidog-specific extensions, import specifications via REST API, and maintain synchronized API documentation. **When to use this skill:** - Creating OpenAPI specifications for API documentation - Synchronizing API specs with Apidog projects - Importing endpoints and schemas to Apidog - Managing API documentation lifecycle **See also:** - **dev:bunjs** - Core Bun patterns, HTTP servers, database access - **dev:bunjs-architecture** - Layered architecture, camelCase conventions - **dev:bunjs-production** - Production deployment patterns ## Why Apidog Apidog is a comprehensive API development platform that combines: - **API Design** - Visual OpenAPI editor - **API Documentation** - Auto-generated, always up-to-date docs - **API Testing** - Built-in testing tools - **API Mocking** - Mock servers for frontend development - **Team Collaboration** - Shared workspace for teams ## Environment Variables **Required:** ```bash APIDOG_PROJECT_ID=your-project-id # From Apidog project settings APIDOG_API_TOKEN=your-api-token # From Apidog account settings ``` **How to get these:** 1. **APIDOG_PROJECT_ID**: Open your Apidog project → Settings → Project ID 2. **APIDOG_API_TOKEN**: Apidog Account → Settings → API Tokens → Generate Token ## OpenAPI Spec Creation ### Basic Structure ```yaml openapi: 3.0.0 info: title: My API version: 1.0.0 description: API for managing resources servers: - url: https://api.example.com/v1 description: Production server - url: https://staging-api.example.com/v1 description: Staging server - url: http://localhost:3000 description: Development server components: schemas: # Define reusable data models here securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT paths: # Define API endpoints here ``` ### Field Naming: camelCase (CRITICAL) **ALWAYS use camelCase for all JSON API field names in OpenAPI specs.** ```yaml components: schemas: User: type: object required: - userId - emailAddress properties: userId: # ✅ camelCase type: string format: uuid emailAddress: # ✅ camelCase type: string format: email firstName: # ✅ camelCase type: string lastName: # ✅ camelCase type: string phoneNumber: # ✅ camelCase type: string isActive: # ✅ camelCase boolean type: boolean createdAt: # ✅ camelCase timestamp type: string format: date-time updatedAt: # ✅ camelCase timestamp type: string format: date-time # ❌ WRONG: snake_case # user_id, email_address, first_name, created_at # ❌ WRONG: PascalCase # UserId, EmailAddress, FirstName, CreatedAt ``` **Why camelCase:** - Native to JavaScript/JSON ecosystem - Industry standard (Google, Microsoft, AWS) - TypeScript friendly (1:1 mapping) - OpenAPI/Swagger convention - Auto-generated clients expect it ### Schema Design **Define reusable schemas in `components.schemas`:** ```yaml components: schemas: User: type: object required: - userId - emailAddress - firstName - lastName properties: userId: type: string format: uuid description: Unique user identifier emailAddress: type: string format: email description: User email address firstName: type: string minLength: 2 maxLength: 100 lastName: type: string minLength: 2 maxLength: 100 phoneNumber: type: string pattern: '^\+?[1-9]\d{1,14}$' role: type: string enum: [user, admin, moderator] default: user isActive: type: boolean default: true createdAt: type: string format: date-time updatedAt: type: string format: date-time CreateUserRequest: type: object required: - emailAddress - password - firstName - lastName properties: emailAddress: type: string format: email password: type: string format: password minLength: 8 firstName: type: string minLength: 2 lastName: type: string minLength: 2 phoneNumber: type: string role: type: string enum: [user, admin, moderator] UserListResponse: type: object properties: data: type: array items: $ref: '#/components/schemas/User' pagination: $ref: '#/components/schemas/Pagination' Pagination: type: object properties: page: type: integer minimum: 1 pageSize: type: integer minimum: 1 maximum: 100 total: type: integer totalPages: type: integer ErrorResponse: type: object properties: statusCode: type: integer type: type: string message: type: string details: type: array items: type: object properties: field: type: string message: type: string ``` ### Endpoint Definitions **Define endpoints in `paths`:** ```yaml paths: /users: get: summary: List users description: Retrieve paginated list of users operationId: listUsers tags: - Users security: - bearerAuth: [] x-apidog-folder: User Management/Users x-apidog-status: released x-apidog-maintainer: backend-team parameters: - name: page in: query schema: type: integer minimum: 1 default: 1 - name: pageSize in: query schema: type: integer minimum: 1 maximum: 100 default: 20 - name: sortBy in: query schema: type: string enum: [createdAt, firstName, emailAddress] - name: orderBy in: query schema: type: string enum: [asc, desc] default: desc responses: '200': description: Successful response content: application/json: schema: $ref: '#/components/schemas/UserListResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' post: summary: Create user description: Create a new user account operationId: createUser tags: - Users x-apidog-folder: User Management/Users x-apidog-status: released x-apidog-maintainer: backend-team requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateUserRequest' responses: '201': description: User created successfully content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/User' '400': description: Invalid request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '409': description: User already exists content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /users/{userId}: get: summary: Get user description: Retrieve a single user by ID operationId: getUser tags: - Users security: - bearerAuth: [] x-apidog-folder: User Management/Users x-apidog-status: released parameters: - name: userId in: path required: true schema: type: string format: uuid responses: '200': description: Successful response content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/User' '404': description: User not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' ``` ## Apidog-Specific Extensions ### x-apidog-folder Organize endpoints in folders using `/` to separate levels: ```yaml paths: /users: post: x-apidog-folder: User Management/Users /users/{userId}/profile: get: x-apidog-folder: User Management/Users/Profile /orders: post: x-apidog-folder: Order Management/Orders ``` **Escaping special characters:** - Use `\/` for `/` - Use `\\` for `\` ### x-apidog-status Endpoint lifecycle status: | Status | Description | |--------|-------------| | `designing` | Being designed | | `pending` | Pending implementation | | `developing` | In development | | `integrating` | Integration phase | | `testing` | Being tested | | `tested` | Testing complete | | `released` | Production release | | `deprecated` | Marked for deprecation | | `exception` | Has issues | | `obsolete` | No longer used | | `to be deprecated` | Will be deprecated | ```yaml paths: /users: post: x-apidog-status: released # Fully implemented /beta/feature: post: x-apidog-status: testing # In testing phase /legacy/api: get: x-apidog-status: deprecated # Being phased out ``` ### x-apidog-maintainer Specify owner/maintainer (use Apidog username or nickname): ```yaml paths: /users: post: x-apidog-maintainer: backend-team /admin/settings: put: x-apidog-maintainer: john-doe ``` ## Importing to Apidog via REST API ### Import Process **Step 1: Prepare OpenAPI Spec** Create a complete OpenAPI 3.0 spec in JSON format: ```bash # Save spec to file cat > /tmp/api-spec.json << 'EOF' { "openapi": "3.0.0", "info": { ... }, "paths": { ... } } EOF ``` **Step 2: Import via REST API** ```bash #!/bin/bash # Environment variables (from .env) APIDOG_PROJECT_ID="your-project-id" APIDOG_API_TOKEN="your-api-token" # Read OpenAPI spec OPENAPI_SPEC=$(cat /tmp/api-spec.json | jq -c .) # Import to Apidog curl -X POST "https://api.apidog.com/v1/projects/${APIDOG_PROJECT_ID}/import-openapi" \ -H "Authorization: Bearer ${APIDOG_API_TOKEN}" \ -H "X-Apidog-Api-Version: 2024-03-28" \ -H "Content-Type: application/json" \ -d "{ \"input\": \"${OPENAPI_SPEC}\", \"options\": { \"endpointOverwriteBehavior\": \"AUTO_MERGE\", \"schemaOverwriteBehavior\": \"AUTO_MERGE\", \"updateFolderOfChangedEndpoint\": false, \"prependBasePath\": false } }" ``` ### Import Behavior Options | Option | Description | |--------|-------------| | `AUTO_MERGE` | Automatically merge changes (recommended) | | `OVERWRITE_EXISTING` | Replace existing endpoints/schemas completely | | `KEEP_EXISTING` | Skip changes, keep existing | | `CREATE_NEW` | Create new endpoints/schemas (duplicates existing) | **Recommendation: Use `AUTO_MERGE`** for intelligent merging without losing existing data. ### API Response Format ```json { "data": { "counters": { "endpointCreated": 3, "endpointUpdated": 2, "endpointFailed": 0, "endpointIgnored": 0, "schemaCreated": 5, "schemaUpdated": 1, "schemaFailed": 0, "schemaIgnored": 0, "endpointFolderCreated": 1, "endpointFolderUpdated": 0, "schemaFolderCreated": 0, "schemaFolderUpdated": 0 }, "errors": [] } } ``` ### Error Handling | Status Code | Meaning | |-------------|---------| | 401 | Token is invalid or expired | | 404 | Project ID not found | | 422 | OpenAPI spec validation failed | **Check `data.errors` array for detailed error messages.** ## Workflow ### 1. Create OpenAPI Spec from Code **Step 1: Analyze existing endpoints** ```bash # List all route files find src/routes -name "*.ts" -type f # Read route definitions cat src/routes/user.routes.ts ``` **Step 2: Extract schemas from Zod** ```typescript // src/schemas/user.schema.ts import { z } from 'zod'; export const createUserSchema = z.object({ emailAddress: z.string().email(), password: z.string().min(8), firstName: z.string(), lastName: z.string() }); // Convert to OpenAPI schema manually or use zod-to-json-schema ``` **Step 3: Build OpenAPI spec** Map routes to OpenAPI paths, schemas to components, camelCase fields. ### 2. Validate Spec ```bash # Use online validator # https://editor.swagger.io/ # Or use CLI tool npm install -g swagger-cli swagger-cli validate api-spec.yaml ``` ### 3. Import to Apidog ```bash # Via REST API (automated) ./scripts/import-to-apidog.sh # Or manually in Apidog UI # Import → OpenAPI → Upload file ``` ### 4. Verify in Apidog 1. Open Apidog project: `https://app.apidog.com/project/{APIDOG_PROJECT_ID}` 2. Check imported endpoints appear in correct folders 3. Verify schemas are properly structured 4. Test endpoints with Apidog's testing tools 5. Update descriptions and add examples ### 5. Set Endpoint Status Update `x-apidog-status` based on implementation progress: - `designing` → `developing` → `testing` → `released` ### 6. Share with Team Share Apidog project with team members for: - Frontend integration (use mock servers) - API testing - Documentation review ## Automation Script **scripts/import-to-apidog.sh:** ```bash #!/bin/bash set -e # Load environment variables source .env # Check required variables if [ -z "$APIDOG_PROJECT_ID" ] || [ -z "$APIDOG_API_TOKEN" ]; then echo "Error: APIDOG_PROJECT_ID and APIDOG_API_TOKEN must be set" exit 1 fi # Generate OpenAPI spec (customize based on your needs) SPEC_FILE="/tmp/api-spec-$(date +%Y%m%d-%H%M%S).json" echo "Generating OpenAPI spec..." # Add your spec generation logic here # For example: ts-node scripts/generate-openapi.ts > $SPEC_FILE # Read spec OPENAPI_SPEC=$(cat $SPEC_FILE | jq -c .) # Import to Apidog echo "Importing to Apidog..." RESPONSE=$(curl -s -X POST \ "https://api.apidog.com/v1/projects/${APIDOG_PROJECT_ID}/import-openapi" \ -H "Authorization: Bearer ${APIDOG_API_TOKEN}" \ -H "X-Apidog-Api-Version: 2024-03-28" \ -H "Content-Type: application/json" \ -d "{ \"input\": ${OPENAPI_SPEC}, \"options\": { \"endpointOverwriteBehavior\": \"AUTO_MERGE\", \"schemaOverwriteBehavior\": \"AUTO_MERGE\" } }") # Parse response ENDPOINT_CREATED=$(echo $RESPONSE | jq -r '.data.counters.endpointCreated') ENDPOINT_UPDATED=$(echo $RESPONSE | jq -r '.data.counters.endpointUpdated') SCHEMA_CREATED=$(echo $RESPONSE | jq -r '.data.counters.schemaCreated') SCHEMA_UPDATED=$(echo $RESPONSE | jq -r '.data.counters.schemaUpdated') ERRORS=$(echo $RESPONSE | jq -r '.data.errors | length') # Display summary echo "" echo "✅ Import Complete!" echo "" echo "Endpoints:" echo " Created: $ENDPOINT_CREATED" echo " Updated: $ENDPOINT_UPDATED" echo "" echo "Schemas:" echo " Created: $SCHEMA_CREATED" echo " Updated: $SCHEMA_UPDATED" echo "" echo "Errors: $ERRORS" echo "" echo "🔗 View in Apidog: https://app.apidog.com/project/${APIDOG_PROJECT_ID}" # Exit with error if there were errors if [ "$ERRORS" != "0" ]; then echo "" echo "⚠️ Import had errors. Check response:" echo $RESPONSE | jq '.data.errors' exit 1 fi ``` ## Error Scenarios & Solutions ### Missing Environment Variables **Problem:** `APIDOG_PROJECT_ID` or `APIDOG_API_TOKEN` not set **Solution:** ```bash # Add to .env file APIDOG_PROJECT_ID=your-project-id APIDOG_API_TOKEN=your-api-token # Restart application ``` ### Schema Conflicts **Problem:** New schema conflicts with existing schema **Solution:** - Use `allOf` to extend existing schemas - Or create with different name - Or use `OVERWRITE_EXISTING` behavior (carefully) ### Import Failures **Problem:** Automated import fails **Solution:** - Check API token validity - Verify project ID - Validate OpenAPI spec syntax - Check `data.errors` in response for details ### Invalid OpenAPI Spec **Problem:** Generated spec has validation errors **Solution:** ```bash # Validate before importing swagger-cli validate api-spec.yaml # Fix validation errors # Common issues: # - Missing required fields # - Invalid $ref paths # - Incorrect enum values # - Wrong data types ``` ## Best Practices ### 1. Schema Reuse ```yaml # ✅ CORRECT: Reuse schemas with $ref paths: /users/{userId}: get: responses: '200': content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/User' # ❌ WRONG: Duplicate schema definitions paths: /users/{userId}: get: responses: '200': content: application/json: schema: type: object properties: data: type: object properties: userId: { type: string } # ... duplicated fields ``` ### 2. Comprehensive Descriptions ```yaml # ✅ CORRECT: Clear descriptions paths: /users: post: summary: Create user description: | Creates a new user account with email verification. The password must meet the following requirements: - At least 8 characters - Contains uppercase and lowercase letters - Contains at least one number - Contains at least one special character Upon successful creation, a verification email is sent to the provided email address. ``` ### 3. Response Examples ```yaml responses: '200': description: Successful response content: application/json: schema: $ref: '#/components/schemas/User' example: data: userId: "550e8400-e29b-41d4-a716-446655440000" emailAddress: "john@example.com" firstName: "John" lastName: "Doe" isActive: true createdAt: "2025-01-06T12:00:00Z" ``` ### 4. Security Schemes ```yaml components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT description: JWT access token obtained from /auth/login # Apply globally security: - bearerAuth: [] # Or per endpoint paths: /public/health: get: security: [] # No auth required ``` ### 5. Version Your API ```yaml servers: - url: https://api.example.com/v1 description: Version 1 (current) - url: https://api.example.com/v2 description: Version 2 (beta) ``` --- *OpenAPI and Apidog integration for Bun.js TypeScript backend. For core patterns, see dev:bunjs. For architecture, see dev:bunjs-architecture.*