# How to Test an OpenAI Plugin Locally: A Complete Developer Guide

> Learn to test your OpenAI plugin locally. This guide covers running your server, using ngrok for HTTPS, updating your manifest, and registering your plugin in the developer console.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: how-to-guide
- Published: 2026-06-14

---

**To test an OpenAI plugin locally, run your plugin server on localhost, expose it via an HTTPS tunnel (ngrok), update the manifest's `host` field with the public URL, and register that URL in the OpenAI developer console's Test tab.**

OpenAI plugins are standard web services defined by a **manifest** file ([`.codex-plugin/plugin.json`](https://github.com/openai/plugins/blob/main/.codex-plugin/plugin.json)) that describes the HTTP API. The `openai/plugins` repository provides scaffolding and reference implementations showing how to develop these plugins on your local machine before deploying to production. Because the OpenAI platform requires HTTPS endpoints, you must tunnel your local development server to obtain a public URL for testing.

## Start the Local Plugin Server

Every plugin begins with a runnable server that exposes the endpoints defined in your manifest. According to the source code in the `openai/plugins` repository, the **plugin-creator** skill generates starter servers from [`.agents/skills/plugin-creator/scripts/create_basic_plugin.py`](https://github.com/openai/plugins/blob/main/.agents/skills/plugin-creator/scripts/create_basic_plugin.py), typically producing a Python Flask or Node.js Express application.

Create a minimal Flask server to handle plugin operations:

```python

# server.py – Local development server

from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/openai/v1/operations/list_items", methods=["POST"])
def list_items():
    return jsonify({"items": ["Item 1", "Item 2"]})

if __name__ == "__main__":
    app.run(port=5000)

```

Run the server locally:

```bash
python server.py

```

Your plugin now runs on `http://localhost:5000`, but the OpenAI platform rejects plain HTTP addresses. You must create a secure tunnel to expose this locally.

## Expose Localhost via HTTPS Tunnel

The OpenAI platform only accepts **HTTPS URLs**, requiring you to tunnel your local `http://localhost` endpoint to the public internet. The reference documentation in [`plugins/zoom/skills/zoom-apps-sdk/references/full-guide.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/zoom-apps-sdk/references/full-guide.md) explicitly recommends **ngrok** for this purpose.

Install ngrok and create a tunnel to your local port:

```bash
ngrok http 5000

```

Ngrok generates a public URL like `https://1234abcd.ngrok.io` and provides a web interface (typically at `http://127.0.0.1:4040`) for inspecting incoming requests. As noted in [`plugins/zoom/skills/zoom-apps-sdk/troubleshooting/debugging.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/zoom-apps-sdk/troubleshooting/debugging.md), this request inspector is invaluable for debugging payload structure and authentication headers during local development.

## Configure the Plugin Manifest

Each plugin contains a manifest at `plugins/<name>/.codex-plugin/plugin.json` that defines the `host`, authentication methods, and API specification. You must update the `host` field and any OAuth callback URLs to match your ngrok tunnel address.

Update your manifest to point to the public tunnel:

```json
{
  "schema_version": "v1",
  "name_for_human": "Example Plugin",
  "name_for_model": "example_plugin",
  "description_for_human": "Demo plugin for local testing.",
  "description_for_model": "Provides a list of example items.",
  "auth": {
    "type": "none"
  },
  "api": {
    "type": "openapi",
    "url": "https://1234abcd.ngrok.io/openapi.yaml"
  },
  "host": "https://1234abcd.ngrok.io"
}

```

The `host` field must match exactly with the ngrok URL, including the protocol. If your plugin uses webhooks or OAuth redirects, those endpoints must also use this public URL to allow the OpenAI platform to reach your local machine.

## Register the Tunnel in the OpenAI Developer Console

With your server running and manifest updated, register the plugin in the OpenAI platform to enable testing through the ChatGPT interface.

1. Navigate to **OpenAI Platform → Plugins → Create a plugin → Add a custom plugin**.
2. Paste your ngrok URL (`https://1234abcd.ngrok.io`) into the **Plugin URL** field.
3. Click **Fetch** to validate the manifest and load the API specification.

The console verifies that the manifest is accessible and the endpoints respond correctly. Once validation passes, the **Test** tab becomes available, allowing you to invoke plugin actions directly from the ChatGPT UI while requests route through your local tunnel.

## Test and Debug Live Requests

After registration, use the **Test** view in the developer console to send live requests to your local server. When you invoke an action like `list_items`, the request travels through the ngrok tunnel, hits your Flask endpoint, and returns the response to the ChatGPT interface.

Monitor the ngrok inspector (at `http://127.0.0.1:4040`) to examine request headers, payload bodies, and response codes in real-time. This visibility allows you to debug authentication failures, schema mismatches, or business logic errors without deploying to a remote server.

If your plugin supports OAuth, ensure the redirect URL in your OAuth configuration also points to the ngrok tunnel (e.g., `https://1234abcd.ngrok.io/auth/callback`). The temporary authorization code must be exchanged for an access token securely on your server side, never in frontend storage, as detailed in [`plugins/zoom/skills/oauth/references/oauth-errors.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/oauth/references/oauth-errors.md).

## Handling OAuth Flows During Local Development

Plugins requiring authentication must handle OAuth redirects through the same ngrok tunnel. When configuring OAuth in the developer console:

- Set the **Redirect URL** to your ngrok address (e.g., `https://1234abcd.ngrok.io/oauth/callback`).
- Ensure your local server implements the token exchange at this endpoint.
- Store access tokens securely server-side; avoid exposing them in client-side code.

Because the tunnel URL persists until you stop ngrok, you can iterate on code changes, restart your local server, and re-test immediately without updating the manifest or console configuration.

## Summary

- **HTTPS is mandatory**: The OpenAI platform rejects HTTP URLs, requiring ngrok or similar tunneling services for local development.
- **Manifest configuration**: Update the `host` field in [`.codex-plugin/plugin.json`](https://github.com/openai/plugins/blob/main/.codex-plugin/plugin.json) to your public tunnel URL before registering the plugin.
- **Developer console workflow**: Use **Platform → Plugins → Add a custom plugin** to fetch your manifest and enable the Test tab for live invocation.
- **Debug via ngrok**: Inspect request headers and payloads through the ngrok web interface (`http://127.0.0.1:4040`) to troubleshoot integration issues.
- **OAuth compatibility**: Redirect URLs and webhook endpoints must all reference the same public tunnel address during local testing.

## Frequently Asked Questions

### Why can't I use localhost directly for testing OpenAI plugins?

The OpenAI platform requires all plugin endpoints to use HTTPS for security reasons, and it cannot reach private IP addresses or `localhost` on your development machine. As implemented in the `openai/plugins` repository, you must use a tunneling service like ngrok to expose your local server through a public HTTPS URL that the platform can access and validate.

### How do I update the plugin manifest for local testing?

Edit the [`plugin.json`](https://github.com/openai/plugins/blob/main/plugin.json) file located at [`.codex-plugin/plugin.json`](https://github.com/openai/plugins/blob/main/.codex-plugin/plugin.json) within your plugin directory. Change the `host` field to your ngrok URL (e.g., `https://1234abcd.ngrok.io`) and ensure the `api.url` field points to your OpenAPI specification using the same base URL. This tells the OpenAI platform where to send requests when you test the plugin.

### What is the fastest way to debug requests when testing locally?

Run ngrok with the command `ngrok http <your-port>` and open the inspector at `http://127.0.0.1:4040` to see every HTTP request sent from the OpenAI platform to your local server. This allows you to verify headers, inspect JSON payloads, and identify authentication errors before they reach your application logic, as recommended in the Zoom SDK troubleshooting guides within the repository.

### Do I need to reinstall the plugin in the console after every code change?

No. As long as you keep the same ngrok tunnel running (without restarting ngrok), the public URL remains constant. You can modify your plugin code, restart your local server, and click **Test** again in the OpenAI developer console immediately. The changes reflect instantly because the tunnel URL and manifest `host` field remain unchanged.