How to Define API Endpoints in an OpenAI Plugin: A Complete Guide

OpenAI plugins expose HTTP capabilities through a manifest file (.codex-plugin/plugin.json) that references an OpenAPI specification describing the available REST endpoints.

The openai/plugins repository provides the reference architecture for extending ChatGPT with custom capabilities. To define API endpoints in an OpenAI plugin, you must declare an api block in your plugin manifest that points to a valid OpenAPI 3.0 specification hosted on a public HTTPS URL.

Understanding the Plugin Manifest Structure

Every OpenAI plugin requires a manifest file located at .codex-plugin/plugin.json in your repository root. This JSON file declares the plugin's metadata and, crucially, the location of its API specification.

The api block is the only required element for exposing HTTP endpoints. It contains two fields:

  • type: Must be set to "openapi"
  • url: A publicly accessible HTTPS URL pointing to your OpenAPI document

Additional optional blocks include auth for authentication flows and hooks for lifecycle events, but the api entry alone enables the model to discover and invoke your endpoints.

For a production example, examine the Zoom plugin manifest at plugins/zoom/.codex-plugin/plugin.json, which demonstrates how to structure the api and auth configurations for a real-world REST API.

Creating the OpenAPI Specification

The OpenAPI specification enumerates every endpoint the model can call. This document must be hosted at the URL specified in your manifest and must use the OpenAPI 3.0.1 format.

Your specification requires three critical components:

  1. servers: Defines the base URL for all API calls
  2. paths: Lists each endpoint with HTTP methods, parameters, and response schemas
  3. operationId: A unique identifier for each operation that the model uses to invoke the function

Below is a minimal example defining a single GET endpoint:

openapi: 3.0.1
info:
  title: Weather Service
  version: "1.0"
servers:
  - url: https://api.myweather.com/v1
paths:
  /forecast:
    get:
      summary: Get a weather forecast
      operationId: getForecast
      parameters:
        - in: query
          name: city
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Forecast'
components:
  schemas:
    Forecast:
      type: object
      properties:
        temperature:
          type: number
        conditions:
          type: string

Reference the Zoom plugin's OpenAPI documentation at plugins/zoom/skills/rest-api/references/openapi.md to see how complex REST APIs structure their path hierarchies and security schemes.

Wiring the Specification into the Manifest

Once your OpenAPI document is hosted on a public HTTPS endpoint, update .codex-plugin/plugin.json to reference it:

{
  "name": "weather-plugin",
  "description": "Provides real-time weather data",
  "api": {
    "type": "openapi",
    "url": "https://raw.githubusercontent.com/your-org/weather-plugin/main/openapi.yaml"
  },
  "auth": {
    "type": "none"
  }
}

Critical requirements for the URL:

  • Must use HTTPS (TLS required)
  • Must be publicly accessible without authentication
  • Must remain stable (avoid temporary URLs in production)

For local development, you can use a tunneling service like ngrok to expose localhost temporarily, but remember to update the manifest with your production URL before submission.

Handling Authentication

If your API requires authentication, add an auth block to your manifest instead of using "type": "none". The OpenAI platform supports OAuth 2.0 and API key flows, automatically managing token exchange and injection.

For OAuth implementations, specify the client ID and required scopes:

"auth": {
  "type": "oauth",
  "client_id": "YOUR_CLIENT_ID",
  "scopes": ["weather.read"]
}

For API key authentication, define the security scheme in your OpenAPI specification under components/securitySchemes and reference it from individual operations. The Zoom plugin demonstrates OAuth configuration in plugins/zoom/.codex-plugin/plugin.json and provides additional context in plugins/zoom/skills/zoom-apps-sdk/references/oauth.md.

Validating and Testing Your Endpoints

Before submitting your plugin, validate both the manifest and OpenAPI specification using the repository's built-in test harness.

Run the plugin evaluation suite from the repository root:

npm run test:plugin-eval

This command executes the test file located at plugins/plugin-eval/tests/plugin-eval.test.js, which verifies that your manifest syntax is valid, the OpenAPI document is reachable, and all operationId values are unique.

After validation, test functionality through the OpenAI Playground by enabling the Plugins toggle and loading your plugin. Issue natural language requests that should trigger your endpoints, such as asking for a weather forecast if you implemented the example above. The model will translate these requests into HTTP calls using the operationId mappings you defined.

Summary

  • Define API endpoints in an OpenAI plugin by creating a .codex-plugin/plugin.json manifest with an api block pointing to an OpenAPI specification.
  • Host your OpenAPI 3.0 document on a public HTTPS URL with valid paths, servers, and unique operationId fields for each endpoint.
  • Include an auth block in the manifest if your endpoints require OAuth or API key authentication.
  • Validate your implementation using npm run test:plugin-eval before testing in the OpenAI Playground.
  • Reference the Zoom plugin files in openai/plugins for production-ready examples of manifest structure and OpenAPI definitions.

Frequently Asked Questions

What file format should the OpenAPI specification use?

The specification must use OpenAPI 3.0.1 format, written in either YAML or JSON. The document must include servers, paths, and components/schemas sections, with each operation defining a unique operationId that serves as the function name the model invokes.

Can I use localhost URLs during development?

No, the manifest requires publicly accessible HTTPS URLs. For local development, use a tunneling service like ngrok to create a temporary public URL pointing to your localhost server. Remember to replace the temporary URL with your production endpoint before finalizing the plugin.

How does the model know which endpoint to call for a specific user request?

The model reads your OpenAPI specification to understand available capabilities. When a user makes a relevant request, the model maps the intent to the appropriate operationId in your spec and constructs the HTTP request using the defined parameters, base URL from servers, and authentication details from the manifest's auth block.

What validation errors commonly prevent plugin installation?

Common failures include non-HTTPS URLs in the api.url field, missing or duplicate operationId values in the OpenAPI spec, unreachable endpoints, and mismatches between the name field in the manifest and the repository directory name. Run npm run test:plugin-eval to catch these issues before submission.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →