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:
- servers: Defines the base URL for all API calls
- paths: Lists each endpoint with HTTP methods, parameters, and response schemas
- 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.jsonmanifest with anapiblock pointing to an OpenAPI specification. - Host your OpenAPI 3.0 document on a public HTTPS URL with valid
paths,servers, and uniqueoperationIdfields for each endpoint. - Include an
authblock in the manifest if your endpoints require OAuth or API key authentication. - Validate your implementation using
npm run test:plugin-evalbefore testing in the OpenAI Playground. - Reference the Zoom plugin files in
openai/pluginsfor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →