OpenAPI Recipes for GPT Actions (Copy/Paste)
Practical specs you can drop into the GPT builder. Swap api.example.com, keep responses small, and write friendly tool descriptions.
Last updated:
TL;DR
- Start with a minimal spec, add auth later.
- Provide plain-English operation descriptions so the GPT knows when to call.
- Return concise JSON with stable field names.
- Add an error model and examples for 4xx/5xx.
- Set a decision rule in Instructions: “When user asks for X, call getX first.”
Quick Start: Spec Skeleton
openapi: 3.1.0
info: { title: My API, version: '1.0.0' }
servers: [ { url: https://api.example.com } ]
paths: {}
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
schemas:
Error:
type: object
properties:
error: { type: string }
code: { type: string }
Auth Patterns (drop-in)
API Key (header)
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
security:
- ApiKeyAuth: []
Bearer Token
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
security:
- BearerAuth: []
OAuth2 (Auth Code)
components:
securitySchemes:
OAuth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.example.com/oauth/authorize
tokenUrl: https://auth.example.com/oauth/token
scopes:
read: Read data
write: Write data
security:
- OAuth2: [read, write]
Recipes
Each recipe includes a tool-friendly description, parameters, and compact JSON responses.
1) Weather (read-only, no auth)
Use for demos. Keep outputs tiny: temperature and summary only.
openapi: 3.1.0
info: { title: Weather Action, version: '1.0.0' }
servers: [ { url: https://api.example.com } ]
paths:
/weather:
get:
operationId: getWeather
description: "Gets current weather for a city. Use when user asks about temperature or conditions."
parameters:
- in: query
name: city
required: true
schema: { type: string }
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
tempC: { type: number }
summary: { type: string }
'400': { $ref: '#/components/responses/BadRequest' }
components:
responses:
BadRequest:
description: Bad Request
content:
application/json:
schema:
type: object
properties:
error: { type: string }
code: { type: string }
2) Append to a Sheet (api key)
Great for logs, leads, or feedback. Requires a header API key.
openapi: 3.1.0
info: { title: Sheets Action, version: '1.0.0' }
servers: [ { url: https://api.example.com } ]
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
paths:
/sheets/{sheetId}/append:
post:
operationId: appendRow
description: "Appends a row of values to the given sheet. Use for logs or signups."
security: [ { ApiKeyAuth: [] } ]
parameters:
- in: path
name: sheetId
required: true
schema: { type: string }
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
values:
type: array
items: { type: string }
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
ok: { type: boolean }
rowNumber: { type: integer }
3) Create Support Ticket (bearer)
Collect user issue → create ticket. Include a minimal required set of fields.
openapi: 3.1.0
info: { title: Support Ticket Action, version: '1.0.0' }
servers: [ { url: https://api.example.com } ]
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
paths:
/tickets:
post:
operationId: createTicket
description: "Creates a support ticket. Use when the user reports a bug or issue."
security: [ { BearerAuth: [] } ]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [subject, description]
properties:
subject: { type: string }
description: { type: string }
priority: { type: string, enum: [low, medium, high] }
email: { type: string, format: email }
responses:
'201':
description: Created
content:
application/json:
schema:
type: object
properties:
id: { type: string }
url: { type: string, format: uri }
4) Search (paginated)
Keep fields minimal: title, url, snippet. Add pagination parameters with sane defaults.
openapi: 3.1.0
info: { title: Search Action, version: '1.0.0' }
servers: [ { url: https://api.example.com } ]
paths:
/search:
get:
operationId: search
description: "Searches the catalog. Use for 'find X' requests."
parameters:
- in: query
name: q
required: true
schema: { type: string }
- in: query
name: page
schema: { type: integer, default: 1, minimum: 1 }
- in: query
name: pageSize
schema: { type: integer, default: 5, minimum: 1, maximum: 10 }
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
type: object
properties:
title: { type: string }
url: { type: string, format: uri }
snippet: { type: string }
page: { type: integer }
totalPages: { type: integer }
5) Trigger Job (idempotent)
Useful for starting background tasks. Include an Idempotency-Key header to avoid duplicates.
openapi: 3.1.0
info: { title: Jobs Action, version: '1.0.0' }
servers: [ { url: https://api.example.com } ]
paths:
/jobs:
post:
operationId: triggerJob
description: "Triggers a background job. Use when the user asks to start processing."
parameters:
- in: header
name: Idempotency-Key
required: true
schema: { type: string }
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [type]
properties:
type: { type: string, enum: [import, export, analysis] }
payload: { type: object, additionalProperties: true }
responses:
'202':
description: Accepted
content:
application/json:
schema:
type: object
properties:
jobId: { type: string }
status: { type: string, enum: [queued, running] }
6) Send Notification (webhook)
Post a short message to your webhook endpoint. Add per-channel routing if needed.
openapi: 3.1.0
info: { title: Notify Action, version: '1.0.0' }
servers: [ { url: https://api.example.com } ]
paths:
/notify:
post:
operationId: sendNotification
description: "Sends a short message (<= 280 chars) to a webhook or chat relay."
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [message]
properties:
channel: { type: string, enum: [alerts, sales, support], default: alerts }
message: { type: string, maxLength: 280 }
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
ok: { type: boolean }
deliveredAt: { type: string, format: date-time }
7) Create Issue (labels)
Create a tracker issue with optional labels; returns a URL.
openapi: 3.1.0
info: { title: Issues Action, version: '1.0.0' }
servers: [ { url: https://api.example.com } ]
paths:
/repos/{repo}/issues:
post:
operationId: createIssue
description: "Creates an issue in the repository. Use when the user requests tracking a bug or task."
parameters:
- in: path
name: repo
required: true
schema: { type: string }
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [title]
properties:
title: { type: string }
body: { type: string }
labels: { type: array, items: { type: string }, maxItems: 5 }
responses:
'201':
description: Created
content:
application/json:
schema:
type: object
properties:
id: { type: integer }
url: { type: string, format: uri }
Tool Descriptions (tell the GPT when to call)
getWeather: "Fetch current weather for a city: returns { tempC, summary }. Use when user asks about today's weather."
appendRow: "Append a row of values to a sheet: use for logging signups or feedback."
createTicket: "Create a support ticket when a user reports a bug or issue; include subject and description."
search: "Search the catalog and return up to 5 concise results: title, url, snippet."
triggerJob: "Start a background job (import/export/analysis). Use when the user asks to start processing."
sendNotification: "Send a short message to a team channel via webhook."
Error Model & Examples
Standard error schema
components:
schemas:
Error:
type: object
properties:
error: { type: string }
code: { type: string }
details: { type: object, additionalProperties: true }
Return informative 4xx
responses:
'400':
description: Bad Request
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
examples:
missingParam:
summary: city is required
value: { error: 'city is required', code: 'MISSING_PARAM' }
Publishing Checklist (for Actions)
- Public privacy policy URL.
- Domain verification (TXT record or hosted file).
- Describe each Action in plain English (what, when, inputs, outputs).
- Don’t send PII unless essential; never send secrets from users.
- Log errors server‑side; return concise error messages to the GPT.
FAQ
Where do I host the spec?
Anywhere publicly reachable: your domain or API docs. Keep the URL stable.
How big should responses be?
Small. Prefer the 3–6 fields the GPT needs to answer a question clearly.
Can I secure per‑operation?
Yes. Apply security: at the operation level to override global security.
How do I debug?
Add a short line to the response (during testing) like “source: createTicket” and check your server logs.