API Documentation Writer
Run ID: 69c93d5cfee1f7eb4a80fcf22026-03-29Development
PantheraHive BOS
BOS Dashboard

As part of the "API Documentation Writer" workflow, we are excited to deliver the comprehensive, professionally crafted content for your API documentation. This output is designed to be immediately publishable, providing your developers with clear, actionable information to integrate with your services seamlessly.


Product Catalog API Documentation

Welcome to the Product Catalog API!

Unlock the full potential of your product data with our robust and intuitive Product Catalog API. Designed for developers, this API provides a powerful and flexible way to manage, retrieve, and update your product information programmatically. Whether you're building an e-commerce platform, a mobile application, or integrating with third-party systems, our API offers the tools you need to streamline your operations and enhance your user experience.

What You Can Do


Getting Started

To begin integrating with the Product Catalog API, follow these simple steps. This section covers authentication, base URLs, and a quick example to get you up and running.

1. Authentication

All requests to the Product Catalog API require authentication using an API Key. This key must be included in the X-API-Key header of every request.

Example:

text • 1,744 chars
---

## Core Concepts

Understanding these core concepts will help you interact with the Product Catalog API effectively and handle various scenarios gracefully.

### Data Formats

All request and response bodies are formatted as **JSON (JavaScript Object Notation)**.
Ensure your requests include the `Content-Type: application/json` header for `POST` and `PUT` requests.
Responses will always include `Content-Type: application/json`.

### Error Handling

The API uses standard HTTP status codes to indicate the success or failure of a request. In case of an error (status code 4xx or 5xx), the API will return a JSON object with details about the error.

**Common Error Status Codes:**

| Status Code | Description                                  |
| :---------- | :------------------------------------------- |
| `200 OK`    | Request successful.                          |
| `201 Created` | Resource successfully created.               |
| `204 No Content` | Request successful, no content to return. (e.g., DELETE) |
| `400 Bad Request` | The request was malformed or invalid. (e.g., missing required fields) |
| `401 Unauthorized` | Authentication failed or missing API key. |
| `403 Forbidden` | Access to the resource is forbidden. (e.g., insufficient permissions) |
| `404 Not Found` | The requested resource does not exist.     |
| `405 Method Not Allowed` | The HTTP method used is not supported for this endpoint. |
| `409 Conflict` | The request could not be completed due to a conflict with the current state of the resource. (e.g., duplicate ID) |
| `429 Too Many Requests` | You have exceeded the rate limit.       |
| `500 Internal Server Error` | An unexpected error occurred on the server. |

**Error Response Example:**

Sandboxed live preview

Step 1: Collaboration & Initial Analysis - API Documentation Project

Project Title: Comprehensive API Documentation for [Client/Product Name - Placeholder for actual client input]

Workflow Step: collab → analyze


1. Project Overview & Understanding

Based on our initial collaborative discussions and the provided context, the primary objective is to develop comprehensive, clear, and user-friendly API documentation for the [Client/Product Name] API. This documentation is critical for enabling external developers to seamlessly integrate with our services, reducing support overhead, and accelerating adoption.

The API in question is a RESTful API primarily focused on [e.g., Product Management, Data Synchronization, Payment Processing]. It exposes endpoints for [e.g., CRUD operations on products, retrieving order information, managing user profiles].

Our understanding is that the current state of documentation is fragmented, primarily existing in internal notes, code comments, and informal READMEs, lacking a unified, external-facing resource.

2. Analysis of Current State & Identified Gaps

2.1. API Functionality & Scope

  • Core Functionalities: The API provides essential capabilities for [e.g., Product resource management (create, read, update, delete), Order retrieval and status updates, User authentication and profile management].
  • Key Endpoints: Initial focus is on high-priority endpoints such as /products, /orders, /users/auth.
  • Authentication: The API utilizes [e.g., OAuth 2.0 / API Key authentication].

2.2. Target Audience Profile

  • Primary Audience: External developers, likely with varying levels of experience, integrating third-party applications. They expect clear examples, quick-start guides, and detailed reference material.
  • Secondary Audience: Internal developers for consistency and onboarding, and potentially technical support teams for troubleshooting.

2.3. Existing Documentation Review (Simulated/Assumed)

  • Format & Location: Scattered across internal wikis, Git repositories (in README.md files), and JIRA tickets.
  • Content Quality: Inconsistent in terms of detail, structure, and accuracy. Some sections may be outdated or incomplete.
  • Examples: Limited or no consistent code examples across different languages.
  • Discoverability: Extremely low for external users; challenging even for internal teams.
  • Tooling: No dedicated API documentation platform or standardized tooling in use.

2.4. Identified Gaps and Challenges

  1. Lack of Centralized Source of Truth: No single, unified portal for API consumers.
  2. Inconsistent Information: Discrepancies between different internal documents and the actual API behavior.
  3. Poor Developer Experience (DX): High friction for new integrators due to lack of clear instructions, examples, and interactive elements.
  4. Maintenance Overhead: Current informal approach makes updates difficult and prone to error.
  5. Scalability Issues: As the API evolves, the current documentation strategy will not scale.
  6. Missing Key Components: Lack of essential elements like quick-start guides, authentication flows, error handling, and SDKs (if applicable).

3. Data Insights & Industry Trends

3.1. Impact of High-Quality API Documentation

  • Reduced Time-to-Integration: Studies show that well-documented APIs can reduce integration time by up to 50%, directly impacting developer productivity and satisfaction.
  • Lower Support Costs: Clear documentation deflects common support queries, saving significant resources.
  • Increased API Adoption: Developers are more likely to adopt and use APIs that are easy to understand and integrate.
  • Brand Reputation: Professional documentation enhances the perception of the API provider as reliable and developer-friendly.

3.2. Current Trends in API Documentation

  1. OpenAPI Specification (OAS/Swagger): Rapidly becoming the industry standard for describing RESTful APIs. It allows for machine-readable API definitions, enabling automated documentation generation, client SDK generation, and testing.
  2. Interactive Documentation: Tools like Swagger UI or Postman collections allow developers to interact with the API directly from the documentation, testing endpoints and observing responses.
  3. Code Samples & SDKs: Providing code examples in multiple popular languages (e.g., Python, JavaScript, cURL) significantly aids developers. SDKs abstract away direct API calls, further simplifying integration.
  4. Developer Portals: Dedicated platforms that centralize documentation, authentication, rate limits, forums, and other developer resources.
  5. User-Centric Design: Focusing on the developer's journey, from quick-start to advanced topics, with clear navigation and search functionality.
  6. Version Control & CI/CD for Docs: Treating documentation as code, storing it in Git, and integrating its publication into CI/CD pipelines ensures accuracy and consistency.

4. Recommendations & Strategic Approach

Based on the analysis, we recommend a strategic approach focused on standardization, automation, and developer experience.

4.1. Documentation Strategy

  • Adopt OpenAPI Specification (OAS): This is paramount. We will define the API using OAS (version 3.x), which will serve as the single source of truth for the API's structure, endpoints, parameters, and responses.
  • Structured Content: Organize documentation logically, starting with introductory material (quick start, authentication) and progressing to detailed reference (endpoints, models), advanced topics (webhooks, error handling), and FAQs.
  • Developer Portal Approach: While a full portal may be a later phase, the documentation should be designed to fit into a future developer portal, providing a unified experience.

4.2. Content Prioritization

  1. Quick Start Guide: Essential for immediate developer onboarding.
  2. Authentication & Authorization: Detailed guide on how to obtain and use API keys/tokens.
  3. Core Resource Endpoints: Comprehensive documentation for /products, /orders, /users (CRUD operations, request/response bodies, error codes).
  4. Error Handling: A dedicated section explaining common error codes and how to handle them.
  5. Webhooks/Callbacks (if applicable): How to subscribe and receive notifications.
  6. Advanced Topics: Rate limiting, pagination, filtering, etc.

4.3. Technical Stack & Tooling

  • OAS Generator/Editor: Utilize tools that can generate or assist in writing OAS definitions (e.g., Stoplight Studio, Swagger Editor).
  • Documentation Renderer: Use an OAS-compliant rendering tool for interactive documentation (e.g., Swagger UI, ReDoc, Docusaurus with OpenAPI plugins). This ensures consistency and interactivity.
  • Version Control: Host documentation source files (OAS definition, Markdown guides) in a Git repository (e.g., GitHub, GitLab, Bitbucket) for collaboration and versioning.
  • Static Site Generator (Optional but Recommended): For supplementary guides, tutorials, and a richer developer experience (e.g., Docusaurus, Next.js with MDX).

4.4. Collaboration Model

  • Dedicated SME Access: Establish clear channels and scheduled sessions with Product Owners and Lead Developers for technical clarifications and validation.
  • Review & Feedback Loop: Implement a structured review process for documentation drafts involving technical stakeholders and potential pilot users.
  • Documentation as Code: Treat documentation as a shared asset, encouraging contributions and updates from engineering teams through pull requests.

4.5. Style Guide & Standards

  • Adopt a Consistent Voice & Tone: Professional, clear, concise, and action-oriented.
  • Terminology Glossary: Standardize API-specific terms to avoid ambiguity.
  • Code Example Guidelines: Define conventions for code snippets (language, formatting, comments).

5. Next Steps & Action Plan

To move forward efficiently, the following steps are proposed:

  1. Confirmation of Scope & Prioritization:

* Action: Schedule a follow-up meeting with key stakeholders to confirm the specific API endpoints and features to be documented in the initial phase, and agree on the content prioritization.

* Deliverable: Confirmed Scope Document.

  1. Tooling & Environment Setup:

* Action: Evaluate and select the primary OpenAPI specification editor and documentation rendering tool. Set up the Git repository for documentation source.

* Deliverable: Chosen Tooling Stack and Initial Git Repository Setup.

  1. API Schema & Endpoint Definition (OAS Draft):

* Action: Begin drafting the OpenAPI Specification for the high-priority endpoints, leveraging existing code comments and internal documentation. This will involve initial collaboration with development SMEs.

* Deliverable: Draft OpenAPI Specification (.yaml or .json file).

  1. Content Outline & Structure Development:

* Action: Develop a detailed content outline for the documentation portal, mapping out sections like "Getting Started," "Authentication," "API Reference," "Error Codes," etc.

* Deliverable: Detailed Content Outline Document.

  1. SME Interview Schedule:

* Action: Coordinate with the Product Owner and Lead Developer to schedule dedicated interview slots for in-depth technical discussions.

* Deliverable: Interview Schedule.


This analysis provides a robust foundation for building world-class API documentation. By adopting a structured approach, leveraging industry best practices, and focusing on the developer experience, we can significantly enhance the usability and adoption of the [Client/Product Name] API.

json

{

"name": "Wireless Bluetooth Earbuds",

"description": "High-quality wireless earbuds with noise cancellation.",

"price": 79.99,

collab Output

This deliverable provides comprehensive, production-ready code artifacts to support the "API Documentation Writer" workflow. Following the collaborative phase, this step focuses on generating actionable code to both interact with the API and automate the creation of its documentation.


Step 3: Code Generation Deliverable

Overview

This section delivers two core components:

  1. API Client Code (Python): A robust, reusable Python client for interacting with a hypothetical Product Catalog API. This serves as a prime example for how developers can integrate with the API, demonstrating common patterns for making requests, handling responses, and managing errors.
  2. OpenAPI to Markdown Documentation Generator: A Python script coupled with a Jinja2 template to automatically generate human-readable Markdown documentation from an OpenAPI/Swagger specification. This automates a significant part of the documentation writing process, ensuring consistency and accuracy.

These tools are designed to be clear, well-commented, and easily adaptable to your specific API and documentation needs.


1. API Client Code (Python)

This Python client provides a structured way to interact with your API. It's built with best practices in mind, including session management, error handling, and clear method definitions for each API endpoint.

1.1 Prerequisites

To run the API client code, you'll need:

  • Python 3.6+
  • requests library: pip install requests

1.2 api_client.py

This file contains the ProductCatalogClient class, which encapsulates all API interactions.


# api_client.py
import requests
import json
from typing import Dict, Any, List, Optional

class APIClientError(Exception):
    """Custom exception for API client errors."""
    def __init__(self, message: str, status_code: Optional[int] = None, response_data: Optional[Dict] = None):
        super().__init__(message)
        self.status_code = status_code
        self.response_data = response_data

    def __str__(self):
        detail = f"Status Code: {self.status_code}" if self.status_code else "No status code"
        if self.response_data:
            detail += f", Response: {json.dumps(self.response_data, indent=2)}"
        return f"{super().__str__()} ({detail})"

class ProductCatalogClient:
    """
    A Python client for interacting with the Product Catalog API.

    This client provides methods to perform common operations like
    fetching products, creating new products, and retrieving specific products.
    It handles base URL configuration, request headers, and basic error handling.
    """

    def __init__(self, base_url: str, api_key: Optional[str] = None):
        """
        Initializes the ProductCatalogClient.

        Args:
            base_url (str): The base URL of the API (e.g., "https://api.example.com/v1").
            api_key (str, optional): An API key for authentication, if required.
                                     Defaults to None.
        """
        if not base_url:
            raise ValueError("Base URL cannot be empty.")
        self.base_url = base_url.rstrip('/') # Ensure no trailing slash for consistent joining
        self.session = requests.Session()
        self.session.headers.update({
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        })
        if api_key:
            self.session.headers.update({'Authorization': f'Bearer {api_key}'})

    def _request(self, method: str, path: str, **kwargs) -> Dict[str, Any]:
        """
        Makes a generic HTTP request to the API.

        Args:
            method (str): The HTTP method (e.g., 'GET', 'POST', 'PUT', 'DELETE').
            path (str): The API endpoint path (e.g., '/products').
            **kwargs: Arbitrary keyword arguments to pass to requests.request().
                      Common arguments include 'json' for request body or 'params' for query parameters.

        Returns:
            Dict[str, Any]: The JSON response from the API.

        Raises:
            APIClientError: If the API request fails (non-2xx status code).
            requests.exceptions.RequestException: For network-related errors.
        """
        url = f"{self.base_url}{path}"
        try:
            response = self.session.request(method, url, **kwargs)
            response.raise_for_status()  # Raises HTTPError for bad responses (4xx or 5xx)
            return response.json()
        except requests.exceptions.HTTPError as e:
            # Attempt to parse error response from API
            error_data = None
            try:
                error_data = e.response.json()
            except json.JSONDecodeError:
                pass # Response was not JSON
            raise APIClientError(
                f"API request failed for {method} {path}: {e.response.reason}",
                status_code=e.response.status_code,
                response_data=error_data
            ) from e
        except requests.exceptions.RequestException as e:
            raise APIClientError(f"Network or connection error for {method} {path}: {e}") from e
        except json.JSONDecodeError as e:
            raise APIClientError(f"Failed to decode JSON response from {url}: {e}") from e

    def get_products(self, limit: Optional[int] = None) -> List[Dict[str, Any]]:
        """
        Retrieves a list of products.

        API Endpoint: GET /products

        Args:
            limit (int, optional): The maximum number of products to return.

        Returns:
            List[Dict[str, Any]]: A list of product dictionaries.
        """
        params = {}
        if limit is not None:
            if not isinstance(limit, int) or limit <= 0:
                raise ValueError("Limit must be a positive integer.")
            params['limit'] = limit
        return self._request('GET', '/products', params=params)

    def create_product(self, name: str, price: float, description: Optional[str] = None, currency: str = "USD") -> Dict[str, Any]:
        """
        Creates a new product.

        API Endpoint: POST /products

        Args:
            name (str): The name of the product.
            price (float): The price of the product.
            description (str, optional): A description of the product.
            currency (str): The currency of the product price (default: "USD").

        Returns:
            Dict[str, Any]: The newly created product object.
        """
        product_data = {
            'name': name,
            'price': price,
            'currency': currency
        }
        if description:
            product_data['description'] = description
        return self._request('POST', '/products', json=product_data)

    def get_product_by_id(self, product_id: str) -> Dict[str, Any]:
        """
        Retrieves a single product by its ID.

        API Endpoint: GET /products/{productId}

        Args:
            product_id (str): The unique identifier of the product.

        Returns:
            Dict[str, Any]: The product object.
        """
        if not product_id:
            raise ValueError("Product ID cannot be empty.")
        path = f'/products/{product_id}'
        return self._request('GET', path)

    def close_session(self):
        """Closes the underlying requests session."""
        self.session.close()

# Example Usage (for demonstration purposes)
if __name__ == "__main__":
    # --- Configuration ---
    # IMPORTANT: Replace with your actual API base URL
    API_BASE_URL = "https://api.example.com/v1"
    # Optional: If your API requires an API key for Bearer token authentication
    API_KEY = "your_secret_api_key_if_needed" # Keep this secure in production!

    client = ProductCatalogClient(API_BASE_URL, api_key=API_KEY)

    try:
        print(f"--- Interacting with API at {API_BASE_URL} ---")

        # 1. Get a list of products
        print("\nFetching all products (limit 2):")
        products = client.get_products(limit=2)
        for product in products:
            print(f"  - ID: {product.get('id')}, Name: {product.get('name')}, Price: {product.get('price')}")

        # 2. Create a new product
        print("\nCreating a new product:")
        new_product_data = {
            "name": "Smart Watch",
            "price": 199.99,
            "description": "A stylish smart watch with health tracking.",
            "currency": "USD"
        }
        created_product = client.create_product(**new_product_data)
        print(f"  Created Product ID: {created_product.get('id')}, Name: {created_product.get('name')}")

        # Store the ID of the created product for subsequent operations
        product_id_to_fetch = created_product.get('id')

        # 3. Get a specific product by ID
        if product_id_to_fetch:
            print(f"\nFetching product by ID: {product_id_to_fetch}")
            specific_product = client.get_product_by_id(product_id_to_fetch)
            print(f"  Found Product: {specific_product.get('name')}, Price: {specific_product.get('price')}")

        # 4. Example of expected error handling (e.g., product not found)
        print("\nAttempting to fetch a non-existent product (error handling test):")
        try:
            client.get_product_by_id("non-existent-uuid")
        except APIClientError as e:
            print(f"  Successfully caught expected error: {e}")
            if e.status_code == 404:
                print("  (This is expected for a non-existent product)")
            else:
                print(f"  (Unexpected status code: {e.status_code})")

    except APIClientError as e:
        print(f"\nAn API client error occurred: {e}")
    except ValueError as e:
        print(f"\nConfiguration error: {e}")
collab Output

I am pleased to present the comprehensive, detailed, and professional API documentation content. This deliverable is ready for publishing and designed to be engaging, informative, and actionable for your developers.


PantheraHive Widget API Documentation

Welcome to the PantheraHive Widget API!

Unlock the power of custom widgets and seamlessly integrate our dynamic content into your applications. The PantheraHive Widget API provides a robust and flexible way to retrieve, create, update, and manage widgets programmatically. Whether you're building a dashboard, a content management system, or a personalized user experience, our API empowers you to deliver rich, interactive content with ease.

Get Started Today!

Dive into our documentation and discover how simple it is to bring powerful widgets to your platform. We've designed this API with developers in mind, focusing on clarity, consistency, and performance.


1. Overview

The PantheraHive Widget API allows developers to interact with the PantheraHive widget ecosystem. You can fetch lists of available widgets, retrieve detailed information for specific widgets, create new widgets, update existing ones, and manage their lifecycle. Our API adheres to RESTful principles, uses predictable resource-oriented URLs, and leverages standard HTTP response codes.

Key Features:

  • Retrieve Widgets: Access a catalog of pre-built and custom widgets.
  • Manage Widget Data: Create, update, and delete widget configurations and content.
  • Filter & Search: Efficiently find the widgets you need with robust query parameters.
  • Secure Access: All interactions are secured using API keys and industry-standard authentication.

Base URL:

All API requests should be made to the following base URL:

https://api.pantherahive.com/v1


2. Authentication

Access to the PantheraHive Widget API is secured using API Keys. You must include your unique API Key in the Authorization header of every request.

How to Obtain Your API Key:

  1. Log in to your PantheraHive Developer Dashboard.
  2. Navigate to the "API Keys" section.
  3. Generate a new API Key if you don't have one, or use an existing one.
  4. Ensure you keep your API Key secure and do not expose it in client-side code.

Authentication Method:

Include your API Key as a Bearer Token in the Authorization header.

Example:


Authorization: Bearer YOUR_API_KEY

Important Security Note:

Treat your API Key like a password. Do not hardcode it directly into public repositories or client-side applications. Use environment variables or secure credential management systems.


3. Request and Response Formats

All requests and responses for the PantheraHive Widget API are formatted in JSON (JavaScript Object Notation).

Content-Type Header:

For requests with a body (e.g., POST, PUT), you must include the Content-Type header:

Content-Type: application/json

Example JSON Object Structure:


{
  "id": "widget-123",
  "name": "Featured Product Carousel",
  "type": "carousel",
  "status": "active",
  "data": {
    "items": [
      {"productId": "P001", "image": "url/img1.jpg", "caption": "Product A"},
      {"productId": "P002", "image": "url/img2.jpg", "caption": "Product B"}
    ]
  },
  "createdAt": "2023-10-26T10:00:00Z",
  "updatedAt": "2023-10-26T10:30:00Z"
}

4. Error Handling

The PantheraHive Widget API uses standard HTTP status codes to indicate the success or failure of an API request. In case of an error, the API will return a JSON object containing details about the error.

Common HTTP Status Codes:

| Status Code | Description | Meaning |

| :---------- | :-------------------------------------------- | :--------------------------------------------------------------------------------------------------------- |

| 200 OK | Success | The request was successful. |

| 201 Created | Resource Created | A new resource was successfully created. |

| 204 No Content | No Content | The request was successful, but there is no content to return (e.g., successful deletion). |

| 400 Bad Request | Invalid Request Parameters | The request was malformed or contained invalid parameters. Check your request body and query parameters. |

| 401 Unauthorized | Authentication Required / Invalid API Key | Your API Key is missing, invalid, or expired. |

| 403 Forbidden | Access Denied | You do not have the necessary permissions to access this resource or perform this action. |

| 404 Not Found | Resource Not Found | The requested resource does not exist. |

| 405 Method Not Allowed | HTTP Method Not Supported | The HTTP method used is not supported for this endpoint. |

| 409 Conflict | Resource Conflict | The request could not be completed due to a conflict with the current state of the resource (e.g., duplicate ID). |

| 429 Too Many Requests | Rate Limit Exceeded | You have sent too many requests in a given amount of time. See Rate Limiting section. |

| 500 Internal Server Error | Server Error | An unexpected error occurred on the server. Please try again later or contact support. |

| 503 Service Unavailable | Service Temporarily Unavailable | The server is currently unable to handle the request due to maintenance or overload. |

Example Error Response:


{
  "code": "invalid_parameter",
  "message": "The 'name' field is required.",
  "details": [
    {
      "field": "name",
      "issue": "must not be empty"
    }
  ],
  "timestamp": "2023-10-26T10:45:00Z"
}

5. Rate Limiting

To ensure fair usage and maintain service stability, the PantheraHive Widget API enforces rate limits.

  • Limit: 100 requests per minute per API Key.
  • Exceeding the Limit: If you exceed the rate limit, you will receive a 429 Too Many Requests HTTP status code.

Rate Limit Headers:

The following headers are included in every API response to help you manage your request volume:

| Header | Description |

| :----------------- | :--------------------------------------------------- |

| X-RateLimit-Limit | The maximum number of requests allowed in the current window. |

| X-RateLimit-Remaining | The number of requests remaining in the current window. |

| X-RateLimit-Reset | The UTC timestamp (in seconds) when the current rate limit window resets. |

Best Practices:

  • Implement retry logic with exponential backoff for 429 and 503 responses.
  • Monitor X-RateLimit-Remaining to adjust your request frequency.

6. Endpoints

This section details the available API endpoints. Each endpoint description includes:

  • HTTP Method and URL
  • Description of its purpose
  • Path, Query, and Request Body Parameters
  • Example Requests
  • Example Responses (Success and Error)

6.1. Get All Widgets

Retrieve a list of all widgets available in your account.

  • Method: GET
  • URL: /widgets

Description:

Fetches a paginated list of widgets. You can filter and sort the results using query parameters.

Query Parameters:

| Parameter | Type | Description | Required | Default |

| :-------- | :----- | :------------------------------------------------------------------------------ | :------- | :------ |

| page | integer | The page number for pagination. | No | 1 |

| limit | integer | The number of items per page (max 100). | No | 10 |

| type | string | Filter widgets by their type (e.g., carousel, banner, text). | No | All |

| status | string | Filter widgets by their status (e.g., active, draft, archived). | No | All |

| search | string | Search widgets by name or description (case-insensitive partial match). | No | None |

| sort_by | string | Field to sort by (e.g., createdAt, name, updatedAt). | No | createdAt |

| order | string | Sort order (asc for ascending, desc for descending). | No | desc |

Example Request:


curl -X GET \
  'https://api.pantherahive.com/v1/widgets?page=1&limit=5&type=carousel&status=active&sort_by=name&order=asc' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Example Success Response (Status: 200 OK):


{
  "data": [
    {
      "id": "widget-ABC",
      "name": "Homepage Hero Carousel",
      "type": "carousel",
      "status": "active",
      "data": { /* ... widget specific data ... */ },
      "createdAt": "2023-01-15T10:00:00Z",
      "updatedAt": "2023-10-20T14:30:00Z"
    },
    {
      "id": "widget-DEF",
      "name": "Product Spotlight Carousel",
      "type": "carousel",
      "status": "active",
      "data": { /* ... widget specific data ... */ },
      "createdAt": "2023-03-01T09:00:00Z",
      "updatedAt": "2023-09-01T11:00:00Z"
    }
  ],
  "pagination": {
    "totalItems": 25,
    "totalPages": 5,
    "currentPage": 1,
    "itemsPerPage": 5,
    "nextPage": 2,
    "prevPage": null
  }
}

6.2. Get a Specific Widget

Retrieve details for a single widget by its ID.

  • Method: GET
  • URL: /widgets/{widgetId}

Description:

Fetches the full details of a specific widget using its unique identifier.

Path Parameters:

| Parameter | Type | Description | Required |

| :--------- | :----- | :------------------------- | :------- |

| widgetId | string | The unique ID of the widget. | Yes |

Example Request:


curl -X GET \
  'https://api.pantherahive.com/v1/widgets/widget-ABC' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Example Success Response (Status: 200 OK):


{
  "id": "widget-ABC",
  "name": "Homepage Hero Carousel",
  "type": "carousel",
  "status": "active",
  "data": {
    "slides": [
      { "id": "slide-1", "image": "https://example.com/img/hero1.jpg", "title": "New Arrivals", "link": "/shop/new" },
      { "id": "slide-2", "image": "https://example.com/img/hero2.jpg", "title": "Limited Offer", "link": "/shop/offers" }
    ],
    "autoplay": true,
    "intervalMs": 5000
  },
  "createdAt": "2023-01-15T10:00:00Z",
  "updatedAt": "2023-10-20T14:30:00Z"
}

Example Error Response (Status: 404 Not Found):


{
  "code": "resource_not_found",
  "message": "Widget with ID 'widget-XYZ' not found.",
  "timestamp": "2023-10-26T11:00:00Z"
}

6.3. Create a New Widget

Create a new widget with specified properties and content.

  • Method: POST
  • URL: /widgets

Description:

Registers a new widget in the PantheraHive system. The name and type are mandatory. The data field should contain the specific configuration for the widget type.

Request Body Parameters:

| Parameter | Type | Description | Required |

| :-------- | :----- | :------------------------------------------------------------------------------ | :------- |

| name | string | The name of the widget (must be unique). | Yes |

| type | string | The type of the widget (e.g., carousel, banner, text). | Yes |

| status | string | The initial status of the widget (active, draft). | No |

| data | object | JSON object containing widget-specific configuration and content. Schema varies by type. | Yes |

Example Request (Creating a banner widget):


curl -X POST \
  'https://api.pantherahive.com/v1/widgets' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -d '{
        "name": "Homepage Promo Banner",
        "type": "banner",
        "status": "draft",
        "data": {
          "imageUrl": "https://example.com/img/promo-banner.jpg",
          "headline": "Flash Sale! Up to 50% Off",
          "callToAction": "Shop Now",
          "linkUrl": "/shop/flash-sale",
          "backgroundColor": "#FFD700"
        }
      }'

Example Success Response (Status: 201 Created):


{
  "id": "widget-GHI",
  "name": "Homepage Promo Banner",
  "type": "banner",
  "status": "draft",
  "data": {
    "imageUrl": "https://example.com/img/promo-banner.jpg",
    "headline": "Flash Sale! Up to 50% Off",
    "callToAction": "Shop Now",
    "linkUrl": "/shop/flash-sale",
    "backgroundColor": "#FFD700"
  },
  "createdAt": "2023-10-26T11:15:00Z",
  "updatedAt": "2023-10-26T11:15:00Z"
}

Example Error Response (Status: 400 Bad Request - Missing field):


{
  "code": "invalid_parameter",
  "message": "The 'type' field is required.",
  "details": [
api_documentation_writer.txt
Download source file
Copy all content
Full output as text
Download ZIP
IDE-ready project ZIP
Copy share link
Permanent URL for this run
Get Embed Code
Embed this result on any website
Print / Save PDF
Use browser print dialog
\n\n\n"); var hasSrcMain=Object.keys(extracted).some(function(k){return k.indexOf("src/main")>=0;}); if(!hasSrcMain) zip.file(folder+"src/main."+ext,"import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport App from './App'\nimport './index.css'\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n \n \n \n)\n"); var hasSrcApp=Object.keys(extracted).some(function(k){return k==="src/App."+ext||k==="App."+ext;}); if(!hasSrcApp) zip.file(folder+"src/App."+ext,"import React from 'react'\nimport './App.css'\n\nfunction App(){\n return(\n
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n
\n )\n}\nexport default App\n"); zip.file(folder+"src/index.css","*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#f0f2f5;color:#1a1a2e}\n.app{min-height:100vh;display:flex;flex-direction:column}\n.app-header{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px}\nh1{font-size:2.5rem;font-weight:700}\n"); zip.file(folder+"src/App.css",""); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/pages/.gitkeep",""); zip.file(folder+"src/hooks/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\n## Open in IDE\nOpen the project folder in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- Vue (Vite + Composition API + TypeScript) --- */ function buildVue(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "type": "module",\n "scripts": {\n "dev": "vite",\n "build": "vue-tsc -b && vite build",\n "preview": "vite preview"\n },\n "dependencies": {\n "vue": "^3.5.13",\n "vue-router": "^4.4.5",\n "pinia": "^2.3.0",\n "axios": "^1.7.9"\n },\n "devDependencies": {\n "@vitejs/plugin-vue": "^5.2.1",\n "typescript": "~5.7.3",\n "vite": "^6.0.5",\n "vue-tsc": "^2.2.0"\n }\n}\n'); zip.file(folder+"vite.config.ts","import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport { resolve } from 'path'\n\nexport default defineConfig({\n plugins: [vue()],\n resolve: { alias: { '@': resolve(__dirname,'src') } }\n})\n"); zip.file(folder+"tsconfig.json",'{"files":[],"references":[{"path":"./tsconfig.app.json"},{"path":"./tsconfig.node.json"}]}\n'); zip.file(folder+"tsconfig.app.json",'{\n "compilerOptions":{\n "target":"ES2020","useDefineForClassFields":true,"module":"ESNext","lib":["ES2020","DOM","DOM.Iterable"],\n "skipLibCheck":true,"moduleResolution":"bundler","allowImportingTsExtensions":true,\n "isolatedModules":true,"moduleDetection":"force","noEmit":true,"jsxImportSource":"vue",\n "strict":true,"paths":{"@/*":["./src/*"]}\n },\n "include":["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"]\n}\n'); zip.file(folder+"env.d.ts","/// \n"); zip.file(folder+"index.html","\n\n\n \n \n "+slugTitle(pn)+"\n\n\n
\n \n\n\n"); var hasMain=Object.keys(extracted).some(function(k){return k==="src/main.ts"||k==="main.ts";}); if(!hasMain) zip.file(folder+"src/main.ts","import { createApp } from 'vue'\nimport { createPinia } from 'pinia'\nimport App from './App.vue'\nimport './assets/main.css'\n\nconst app = createApp(App)\napp.use(createPinia())\napp.mount('#app')\n"); var hasApp=Object.keys(extracted).some(function(k){return k.indexOf("App.vue")>=0;}); if(!hasApp) zip.file(folder+"src/App.vue","\n\n\n\n\n"); zip.file(folder+"src/assets/main.css","*{margin:0;padding:0;box-sizing:border-box}body{font-family:system-ui,sans-serif;background:#fff;color:#213547}\n"); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/views/.gitkeep",""); zip.file(folder+"src/stores/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\nOpen in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- Angular (v19 standalone) --- */ function buildAngular(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var sel=pn.replace(/_/g,"-"); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "scripts": {\n "ng": "ng",\n "start": "ng serve",\n "build": "ng build",\n "test": "ng test"\n },\n "dependencies": {\n "@angular/animations": "^19.0.0",\n "@angular/common": "^19.0.0",\n "@angular/compiler": "^19.0.0",\n "@angular/core": "^19.0.0",\n "@angular/forms": "^19.0.0",\n "@angular/platform-browser": "^19.0.0",\n "@angular/platform-browser-dynamic": "^19.0.0",\n "@angular/router": "^19.0.0",\n "rxjs": "~7.8.0",\n "tslib": "^2.3.0",\n "zone.js": "~0.15.0"\n },\n "devDependencies": {\n "@angular-devkit/build-angular": "^19.0.0",\n "@angular/cli": "^19.0.0",\n "@angular/compiler-cli": "^19.0.0",\n "typescript": "~5.6.0"\n }\n}\n'); zip.file(folder+"angular.json",'{\n "$schema": "./node_modules/@angular/cli/lib/config/schema.json",\n "version": 1,\n "newProjectRoot": "projects",\n "projects": {\n "'+pn+'": {\n "projectType": "application",\n "root": "",\n "sourceRoot": "src",\n "prefix": "app",\n "architect": {\n "build": {\n "builder": "@angular-devkit/build-angular:application",\n "options": {\n "outputPath": "dist/'+pn+'",\n "index": "src/index.html",\n "browser": "src/main.ts",\n "tsConfig": "tsconfig.app.json",\n "styles": ["src/styles.css"],\n "scripts": []\n }\n },\n "serve": {"builder":"@angular-devkit/build-angular:dev-server","configurations":{"production":{"buildTarget":"'+pn+':build:production"},"development":{"buildTarget":"'+pn+':build:development"}},"defaultConfiguration":"development"}\n }\n }\n }\n}\n'); zip.file(folder+"tsconfig.json",'{\n "compileOnSave": false,\n "compilerOptions": {"baseUrl":"./","outDir":"./dist/out-tsc","forceConsistentCasingInFileNames":true,"strict":true,"noImplicitOverride":true,"noPropertyAccessFromIndexSignature":true,"noImplicitReturns":true,"noFallthroughCasesInSwitch":true,"paths":{"@/*":["src/*"]},"skipLibCheck":true,"esModuleInterop":true,"sourceMap":true,"declaration":false,"experimentalDecorators":true,"moduleResolution":"bundler","importHelpers":true,"target":"ES2022","module":"ES2022","useDefineForClassFields":false,"lib":["ES2022","dom"]},\n "references":[{"path":"./tsconfig.app.json"}]\n}\n'); zip.file(folder+"tsconfig.app.json",'{\n "extends":"./tsconfig.json",\n "compilerOptions":{"outDir":"./dist/out-tsc","types":[]},\n "files":["src/main.ts"],\n "include":["src/**/*.d.ts"]\n}\n'); zip.file(folder+"src/index.html","\n\n\n \n "+slugTitle(pn)+"\n \n \n \n\n\n \n\n\n"); zip.file(folder+"src/main.ts","import { bootstrapApplication } from '@angular/platform-browser';\nimport { appConfig } from './app/app.config';\nimport { AppComponent } from './app/app.component';\n\nbootstrapApplication(AppComponent, appConfig)\n .catch(err => console.error(err));\n"); zip.file(folder+"src/styles.css","* { margin: 0; padding: 0; box-sizing: border-box; }\nbody { font-family: system-ui, -apple-system, sans-serif; background: #f9fafb; color: #111827; }\n"); var hasComp=Object.keys(extracted).some(function(k){return k.indexOf("app.component")>=0;}); if(!hasComp){ zip.file(folder+"src/app/app.component.ts","import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\n\n@Component({\n selector: 'app-root',\n standalone: true,\n imports: [RouterOutlet],\n templateUrl: './app.component.html',\n styleUrl: './app.component.css'\n})\nexport class AppComponent {\n title = '"+pn+"';\n}\n"); zip.file(folder+"src/app/app.component.html","
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n \n
\n"); zip.file(folder+"src/app/app.component.css",".app-header{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:60vh;gap:16px}h1{font-size:2.5rem;font-weight:700;color:#6366f1}\n"); } zip.file(folder+"src/app/app.config.ts","import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';\nimport { provideRouter } from '@angular/router';\nimport { routes } from './app.routes';\n\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideZoneChangeDetection({ eventCoalescing: true }),\n provideRouter(routes)\n ]\n};\n"); zip.file(folder+"src/app/app.routes.ts","import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n"); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nng serve\n# or: npm start\n\`\`\`\n\n## Build\n\`\`\`bash\nng build\n\`\`\`\n\nOpen in VS Code with Angular Language Service extension.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n.angular/\n"); } /* --- Python --- */ function buildPython(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/m,"").trim(); var reqMap={"numpy":"numpy","pandas":"pandas","sklearn":"scikit-learn","tensorflow":"tensorflow","torch":"torch","flask":"flask","fastapi":"fastapi","uvicorn":"uvicorn","requests":"requests","sqlalchemy":"sqlalchemy","pydantic":"pydantic","dotenv":"python-dotenv","PIL":"Pillow","cv2":"opencv-python","matplotlib":"matplotlib","seaborn":"seaborn","scipy":"scipy"}; var reqs=[]; Object.keys(reqMap).forEach(function(k){if(src.indexOf("import "+k)>=0||src.indexOf("from "+k)>=0)reqs.push(reqMap[k]);}); var reqsTxt=reqs.length?reqs.join("\n"):"# add dependencies here\n"; zip.file(folder+"main.py",src||"# "+title+"\n# Generated by PantheraHive BOS\n\nprint(title+\" loaded\")\n"); zip.file(folder+"requirements.txt",reqsTxt); zip.file(folder+".env.example","# Environment variables\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n\`\`\`\n\n## Run\n\`\`\`bash\npython main.py\n\`\`\`\n"); zip.file(folder+".gitignore",".venv/\n__pycache__/\n*.pyc\n.env\n.DS_Store\n"); } /* --- Node.js --- */ function buildNode(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/m,"").trim(); var depMap={"mongoose":"^8.0.0","dotenv":"^16.4.5","axios":"^1.7.9","cors":"^2.8.5","bcryptjs":"^2.4.3","jsonwebtoken":"^9.0.2","socket.io":"^4.7.4","uuid":"^9.0.1","zod":"^3.22.4","express":"^4.18.2"}; var deps={}; Object.keys(depMap).forEach(function(k){if(src.indexOf(k)>=0)deps[k]=depMap[k];}); if(!deps["express"])deps["express"]="^4.18.2"; var pkgJson=JSON.stringify({"name":pn,"version":"1.0.0","main":"src/index.js","scripts":{"start":"node src/index.js","dev":"nodemon src/index.js"},"dependencies":deps,"devDependencies":{"nodemon":"^3.0.3"}},null,2)+"\n"; zip.file(folder+"package.json",pkgJson); var fallback="const express=require(\"express\");\nconst app=express();\napp.use(express.json());\n\napp.get(\"/\",(req,res)=>{\n res.json({message:\""+title+" API\"});\n});\n\nconst PORT=process.env.PORT||3000;\napp.listen(PORT,()=>console.log(\"Server on port \"+PORT));\n"; zip.file(folder+"src/index.js",src||fallback); zip.file(folder+".env.example","PORT=3000\n"); zip.file(folder+".gitignore","node_modules/\n.env\n.DS_Store\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\n\`\`\`\n\n## Run\n\`\`\`bash\nnpm run dev\n\`\`\`\n"); } /* --- Vanilla HTML --- */ function buildVanillaHtml(zip,folder,app,code){ var title=slugTitle(app); var isFullDoc=code.trim().toLowerCase().indexOf("=0||code.trim().toLowerCase().indexOf("=0; var indexHtml=isFullDoc?code:"\n\n\n\n\n"+title+"\n\n\n\n"+code+"\n\n\n\n"; zip.file(folder+"index.html",indexHtml); zip.file(folder+"style.css","/* "+title+" — styles */\n*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#fff;color:#1a1a2e}\n"); zip.file(folder+"script.js","/* "+title+" — scripts */\n"); zip.file(folder+"assets/.gitkeep",""); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Open\nDouble-click \`index.html\` in your browser.\n\nOr serve locally:\n\`\`\`bash\nnpx serve .\n# or\npython3 -m http.server 3000\n\`\`\`\n"); zip.file(folder+".gitignore",".DS_Store\nnode_modules/\n.env\n"); } /* ===== MAIN ===== */ var sc=document.createElement("script"); sc.src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"; sc.onerror=function(){ if(lbl)lbl.textContent="Download ZIP"; alert("JSZip load failed — check connection."); }; sc.onload=function(){ var zip=new JSZip(); var base=(_phFname||"output").replace(/\.[^.]+$/,""); var app=base.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")||"my_app"; var folder=app+"/"; var vc=document.getElementById("panel-content"); var panelTxt=vc?(vc.innerText||vc.textContent||""):""; var lang=detectLang(_phCode,panelTxt); if(_phIsHtml){ buildVanillaHtml(zip,folder,app,_phCode); } else if(lang==="flutter"){ buildFlutter(zip,folder,app,_phCode,panelTxt); } else if(lang==="react-native"){ buildReactNative(zip,folder,app,_phCode,panelTxt); } else if(lang==="swift"){ buildSwift(zip,folder,app,_phCode,panelTxt); } else if(lang==="kotlin"){ buildKotlin(zip,folder,app,_phCode,panelTxt); } else if(lang==="react"){ buildReact(zip,folder,app,_phCode,panelTxt); } else if(lang==="vue"){ buildVue(zip,folder,app,_phCode,panelTxt); } else if(lang==="angular"){ buildAngular(zip,folder,app,_phCode,panelTxt); } else if(lang==="python"){ buildPython(zip,folder,app,_phCode); } else if(lang==="node"){ buildNode(zip,folder,app,_phCode); } else { /* Document/content workflow */ var title=app.replace(/_/g," "); var md=_phAll||_phCode||panelTxt||"No content"; zip.file(folder+app+".md",md); var h=""+title+""; h+="

"+title+"

"; var hc=md.replace(/&/g,"&").replace(//g,">"); hc=hc.replace(/^### (.+)$/gm,"

$1

"); hc=hc.replace(/^## (.+)$/gm,"

$1

"); hc=hc.replace(/^# (.+)$/gm,"

$1

"); hc=hc.replace(/\*\*(.+?)\*\*/g,"$1"); hc=hc.replace(/\n{2,}/g,"

"); h+="

"+hc+"

Generated by PantheraHive BOS
"; zip.file(folder+app+".html",h); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\nFiles:\n- "+app+".md (Markdown)\n- "+app+".html (styled HTML)\n"); } zip.generateAsync({type:"blob"}).then(function(blob){ var a=document.createElement("a"); a.href=URL.createObjectURL(blob); a.download=app+".zip"; a.click(); URL.revokeObjectURL(a.href); if(lbl)lbl.textContent="Download ZIP"; }); }; document.head.appendChild(sc); } function phShare(){navigator.clipboard.writeText(window.location.href).then(function(){var el=document.getElementById("ph-share-lbl");if(el){el.textContent="Link copied!";setTimeout(function(){el.textContent="Copy share link";},2500);}});}function phEmbed(){var runId=window.location.pathname.split("/").pop().replace(".html","");var embedUrl="https://pantherahive.com/embed/"+runId;var code='';navigator.clipboard.writeText(code).then(function(){var el=document.getElementById("ph-embed-lbl");if(el){el.textContent="Embed code copied!";setTimeout(function(){el.textContent="Get Embed Code";},2500);}});}