How ChatGPT and Codex Can Use the API
The QR Gen API is a natural fit for OpenAI's tool-use ecosystem. ChatGPT, Codex, Custom GPTs, and Assistants can all call the API to generate QR codes on demand. Because the API requires no authentication and returns images directly via GET requests, integrating it is straightforward in every OpenAI product.
The core idea: define the API as a function the model can call, handle the function call by constructing a URL or fetching the image, and return the result to the model so it can present it to the user.
OpenAI Function Calling Tool Definition
Use this with the Chat Completions API. Pass it in the tools array when creating a chat completion.
{
"type": "function",
"function": {
"name": "generate_qr_code",
"description": "Generate a QR code image for the given data. Returns a URL that renders a QR code as PNG or SVG. Use when the user asks to create, make, or generate a QR code for a URL, text, WiFi network, contact info, or any content.",
"parameters": {
"type": "object",
"properties": {
"data": {
"type": "string",
"description": "The content to encode. URLs, plain text, WiFi config strings (WIFI:T:WPA;S:SSID;P:password;;), vCards, mailto: links, tel: links, or any string."
},
"format": {
"type": "string",
"enum": ["png", "svg"],
"description": "Image format. Default png."
},
"size": {
"type": "integer",
"description": "Image size in pixels, 32-2048. Default 512.",
"minimum": 32,
"maximum": 2048
},
"color": {
"type": "string",
"description": "Foreground color as 6-digit hex without #. Default 000000.",
"pattern": "^[0-9a-fA-F]{6}$"
},
"bg": {
"type": "string",
"description": "Background color as 6-digit hex without #. Default ffffff.",
"pattern": "^[0-9a-fA-F]{6}$"
},
"ec": {
"type": "string",
"enum": ["L", "M", "Q", "H"],
"description": "Error correction level. L=7%, M=15%, Q=25%, H=30%. Default M."
},
"margin": {
"type": "integer",
"description": "Quiet zone in modules, 0-10. Default 4.",
"minimum": 0,
"maximum": 10
}
},
"required": ["data"]
}
}
}Handling the Function Call
When the model responds with a tool_calls entry for generate_qr_code, parse the arguments and construct the API URL:
import json
import urllib.parse
def handle_qr_tool_call(tool_call):
args = json.loads(tool_call.function.arguments)
params = {
"data": args["data"],
"format": args.get("format", "png"),
"size": args.get("size", 512),
"color": args.get("color", "000000"),
"bg": args.get("bg", "ffffff"),
"ec": args.get("ec", "M"),
"margin": args.get("margin", 4),
}
url = "https://qrgenapp.com/api/qr?" + urllib.parse.urlencode(params)
# Return the URL to the model as the tool output
return json.dumps({
"url": url,
"markdown": f"",
"description": f"QR code for: {args['data']}"
})Complete Chat Completions Example
from openai import OpenAI
import json
import urllib.parse
client = OpenAI()
tools = [{
"type": "function",
"function": {
"name": "generate_qr_code",
"description": "Generate a QR code image. Returns a URL.",
"parameters": {
"type": "object",
"properties": {
"data": {"type": "string", "description": "Content to encode"},
"size": {"type": "integer", "default": 512},
"color": {"type": "string", "default": "000000"},
"bg": {"type": "string", "default": "ffffff"},
"ec": {"type": "string", "enum": ["L","M","Q","H"], "default": "M"},
},
"required": ["data"]
}
}
}]
messages = [
{"role": "user", "content": "Make me a QR code for https://mysite.com with a blue foreground"}
]
# First call — model decides to use the tool
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
)
msg = response.choices[0].message
if msg.tool_calls:
tc = msg.tool_calls[0]
args = json.loads(tc.function.arguments)
params = urllib.parse.urlencode({
"data": args["data"],
"size": args.get("size", 512),
"color": args.get("color", "000000"),
"bg": args.get("bg", "ffffff"),
"ec": args.get("ec", "M"),
"format": "png",
})
url = f"https://qrgenapp.com/api/qr?{params}"
# Send the tool result back
messages.append(msg)
messages.append({
"role": "tool",
"tool_call_id": tc.id,
"content": json.dumps({"url": url})
})
# Second call — model presents the result
final = client.chat.completions.create(
model="gpt-4o",
messages=messages,
)
print(final.choices[0].message.content)Custom GPT Action Schema
To add QR code generation as an Action in a Custom GPT, use this OpenAPI specification snippet in the GPT builder's "Actions" configuration:
{
"openapi": "3.1.0",
"info": {
"title": "QR Gen API",
"description": "Generate QR codes as images",
"version": "1.0.0"
},
"servers": [
{ "url": "https://qrgenapp.com" }
],
"paths": {
"/api/qr": {
"get": {
"operationId": "generateQrCode",
"summary": "Generate a QR code image",
"description": "Returns a QR code as PNG or SVG image for the given data",
"parameters": [
{
"name": "data",
"in": "query",
"required": true,
"schema": { "type": "string" },
"description": "Content to encode in the QR code"
},
{
"name": "format",
"in": "query",
"schema": { "type": "string", "enum": ["png", "svg"], "default": "png" },
"description": "Output image format"
},
{
"name": "size",
"in": "query",
"schema": { "type": "integer", "minimum": 32, "maximum": 2048, "default": 512 },
"description": "Image size in pixels"
},
{
"name": "color",
"in": "query",
"schema": { "type": "string", "default": "000000" },
"description": "Foreground hex color without #"
},
{
"name": "bg",
"in": "query",
"schema": { "type": "string", "default": "ffffff" },
"description": "Background hex color without #"
},
{
"name": "ec",
"in": "query",
"schema": { "type": "string", "enum": ["L","M","Q","H"], "default": "M" },
"description": "Error correction level"
},
{
"name": "margin",
"in": "query",
"schema": { "type": "integer", "minimum": 0, "maximum": 10, "default": 4 },
"description": "Quiet zone in modules"
}
],
"responses": {
"200": {
"description": "QR code image",
"content": {
"image/png": {
"schema": { "type": "string", "format": "binary" }
},
"image/svg+xml": {
"schema": { "type": "string" }
}
}
}
}
}
}
}
}Paste this into the "Actions" section of the GPT builder. Set authentication to "None". The Custom GPT will now be able to generate QR codes when users ask for them.
Building a Custom GPT That Generates QR Codes
Here is a step-by-step guide to creating a "QR Code Generator" Custom GPT:
- Go to Explore GPTs > Create in ChatGPT.
- Set the name to something like "QR Code Generator".
- In the Instructions field, add:
You are a QR code generator. When users ask you to create a QR code, use the generateQrCode action to create it. Always encode the data correctly: - For WiFi: WIFI:T:WPA;S:{ssid};P:{password};; - For email: mailto:{address} - For phone: tel:{number} - For URLs: use the full URL including https:// - For plain text: use the text as-is After generating, display the QR code image and explain what it encodes. Suggest scanning it with a phone camera to verify. - Under Actions, click "Create new action" and paste the OpenAPI schema from above.
- Set Authentication to None.
- Publish and test.
OpenAI Assistants API with Tool Outputs
When using the Assistants API, handle the requires_action run status by submitting tool outputs:
from openai import OpenAI
import json
import urllib.parse
client = OpenAI()
# Create an assistant with the QR code tool
assistant = client.beta.assistants.create(
name="QR Code Assistant",
instructions="Generate QR codes when asked. Use the generate_qr_code tool.",
model="gpt-4o",
tools=[{
"type": "function",
"function": {
"name": "generate_qr_code",
"description": "Generate a QR code image URL",
"parameters": {
"type": "object",
"properties": {
"data": {"type": "string"},
"size": {"type": "integer", "default": 512},
"color": {"type": "string", "default": "000000"},
"ec": {"type": "string", "enum": ["L","M","Q","H"], "default": "M"},
},
"required": ["data"]
}
}
}]
)
# Create a thread and run
thread = client.beta.threads.create()
client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="Generate a QR code for https://openai.com"
)
run = client.beta.threads.runs.create_and_poll(
thread_id=thread.id,
assistant_id=assistant.id,
)
# Handle tool calls
if run.status == "requires_action":
tool_outputs = []
for tc in run.required_action.submit_tool_outputs.tool_calls:
args = json.loads(tc.function.arguments)
params = urllib.parse.urlencode({
"data": args["data"],
"size": args.get("size", 512),
"color": args.get("color", "000000"),
"ec": args.get("ec", "M"),
"format": "png",
})
url = f"https://qrgenapp.com/api/qr?{params}"
tool_outputs.append({
"tool_call_id": tc.id,
"output": json.dumps({"url": url})
})
run = client.beta.threads.runs.submit_tool_outputs_and_poll(
thread_id=thread.id,
run_id=run.id,
tool_outputs=tool_outputs,
)
# Get the response
messages = client.beta.threads.messages.list(thread_id=thread.id)
print(messages.data[0].content[0].text.value)Responses API Example
With OpenAI's Responses API, you can define tools and handle them in a single streamlined flow:
from openai import OpenAI
import json
import urllib.parse
client = OpenAI()
tools = [{
"type": "function",
"name": "generate_qr_code",
"description": "Generate a QR code. Returns an image URL.",
"parameters": {
"type": "object",
"properties": {
"data": {"type": "string", "description": "Content to encode"},
"size": {"type": "integer", "default": 512},
"color": {"type": "string", "default": "000000"},
"ec": {"type": "string", "enum": ["L","M","Q","H"], "default": "M"},
},
"required": ["data"]
}
}]
response = client.responses.create(
model="gpt-4o",
input="Create a QR code for my portfolio at https://janedoe.dev",
tools=tools,
)
# Check for tool calls in the output
for item in response.output:
if item.type == "function_call":
args = json.loads(item.arguments)
params = urllib.parse.urlencode({
"data": args["data"],
"size": args.get("size", 512),
"color": args.get("color", "000000"),
"ec": args.get("ec", "M"),
"format": "png",
})
url = f"https://qrgenapp.com/api/qr?{params}"
# Continue the conversation with the tool result
final = client.responses.create(
model="gpt-4o",
previous_response_id=response.id,
input=[{
"type": "function_call_output",
"call_id": item.call_id,
"output": json.dumps({"url": url}),
}],
)
print(final.output_text)Markdown Image Trick
In ChatGPT and other interfaces that render Markdown, the model can display the QR code inline by outputting a Markdown image tag. Instruct the model (via system prompt or tool output) to render the result like this:
Because the QR Gen API returns the image directly from a GET request, the Markdown renderer fetches and displays it inline. No file hosting or base64 encoding is needed.
Python Quick Reference
For scripts and notebooks where you just need to generate a QR code without the chat layer:
import requests
def generate_qr(data, size=512, color="000000", bg="ffffff", ec="M", fmt="png"):
"""Generate a QR code using the QR Gen API."""
response = requests.get("https://qrgenapp.com/api/qr", params={
"data": data,
"size": size,
"color": color,
"bg": bg,
"ec": ec,
"format": fmt,
})
response.raise_for_status()
return response.content
# Save a PNG
with open("qr.png", "wb") as f:
f.write(generate_qr("https://example.com"))
# Save an SVG
with open("qr.svg", "wb") as f:
f.write(generate_qr("https://example.com", fmt="svg"))
# WiFi QR code
wifi = "WIFI:T:WPA;S:MyNetwork;P:MyPassword;;"
with open("wifi.png", "wb") as f:
f.write(generate_qr(wifi, ec="H"))Full API Reference
See all parameters, response formats, error codes, and examples in the complete API documentation.
API Docs