Guide
From REST API endpoints to useful ChatGPT tools
A REST API exposes endpoints. A ChatGPT tool exposes a task. The gap between them is design work: deciding which question a person is trying to answer, which single operation can answer it, what input that operation needs and which part of the response deserves to be shown.
Start with the user's question, not the endpoint list
Write the question in ordinary language before you open the specification. “Which region is serving traffic?” is a task. “GET /regions” is an implementation detail. A good tool keeps that distinction visible in its name, its description and the result it returns.
Endpoint inventories encourage breadth: dozens of operations, every field, every filter. A conversational tool benefits from depth on one job. If the user asks for a status, the tool should answer that question and stop. Other operations can become separate tools when they serve separate tasks.
Choose one operation and one job
Map the question to the smallest supported operation that can answer it. Prefer a read over a write, a public operation over one that needs new authorization and a stable identifier over a fuzzy search when the user already knows the record. If two operations are needed for the first version, check whether the tool is still one understandable task.
Design the input around what the user knows
Inputs should match the language of the conversation, not the internal database. A path parameter named region and a query parameter named service may be exactly right. A required tenant_id or internal UUID is not, unless the user genuinely has it. Mark required fields honestly, add descriptions that explain acceptable values and use enums when the valid choices are known.
Turn the response into a useful answer
A response can be technically valid and still be a poor tool result. Select the fields that answer the question, preserve the source wording where it matters and add one timestamp or next step when it changes the decision. Drop debug fields, internal scores and unrelated relationships. Empty and error cases need language too: say what was not found and what the user can try next.
Write the name and description as a proposal
The proposal should make the task legible before anyone builds UI. A name such as get_service_status describes an action; a description such as “Look up the current availability of one service in one region” states when to use it. Treat these strings as design copy that must be reviewed against the real contract. If the wording is vague, improve the operation’s summary, description and operationId in the OpenAPI document, inspect the document again and compare the new proposal. That work happens at the document level; the design still needs validation against the runtime described below.
Example: a public status lookup
Suppose a fictional service publishes GET https://status.example.test/v1/services/{service}?region=eu-west. The path parameter service is required; region is an optional query parameter. The JSON response includes status, summary and updated_at. A user asks, “Is checkout healthy in eu-west right now?” The operation can answer that without exposing the rest of the status API.
- State the question and the expected answer in one sentence.
- Select the single supported GET operation; reject a broader endpoint list for this task.
- Define required and optional inputs and give each one a user-facing description.
- Pick the response fields that support the answer, plus an empty-result message.
- Write one expected case and one failure case before building the interface.
- Decide whether a small status card adds clarity; if not, keep the result headless.
Distinguish design from implemented behavior
The design above is a proposal, not a claim that every REST operation can be imported. The current OpenAPI path accepts a local JSON document, one supported public GET operation, scalar path and query parameters and a JSON success response. Authentication, writes and remote references remain outside that runtime. If you already have an MCP server with suitable tools, inspect that contract instead of translating it back into OpenAPI.
Before you build
Review the proposal with the person who owns the API. Confirm the operation, the required input, the returned fields and the failure language. Then test the operation explicitly with representative input and use that result to shape the optional UI. A local preview can check hierarchy and empty states; it does not prove that a live ChatGPT conversation or the upstream service will behave the same way.