How to Use OpenAI API in R
Introduction
OpenAI’s API gives you access to powerful language models like GPT-4 and GPT-4o directly from R. You can generate text, answer questions, analyze data, and build AI-powered applications.
Alternatives: If you prefer Claude or want to run models locally with Ollama, the ellmer package provides a unified interface for all providers.
What you’ll learn: - Set up OpenAI API access - Use the openai R package - Create chat completions - Handle responses and errors - Manage costs with token limits
Getting Started
Install the openai package
install.packages("openai")
library(openai)Get your API key
- Create an account at platform.openai.com
- Go to API Keys section
- Create a new secret key
- Add billing information (API access requires payment)
Set your API key
# Option 1: Set for current session
Sys.setenv(OPENAI_API_KEY = "sk-your-key-here")
# Option 2: Add to .Renviron (recommended)
usethis::edit_r_environ()
# Add: OPENAI_API_KEY=sk-your-key-hereCreate Chat Completions
The main function for interacting with ChatGPT:
library(openai)
response <- create_chat_completion(
model = "gpt-5.4-mini",
messages = list(
list(role = "user", content = "What is R programming?")
)
)
# Extract the response text
response$choices[[1]]$message$contentWith system prompt
Control the assistant’s behavior:
response <- create_chat_completion(
model = "gpt-5.4-mini",
messages = list(
list(role = "system", content = "You are a helpful R programming tutor."),
list(role = "user", content = "Explain what a data frame is.")
)
)Multi-turn conversation
messages <- list(
list(role = "system", content = "You are an R expert."),
list(role = "user", content = "How do I read a CSV file?"),
list(role = "assistant", content = "Use read.csv() or readr::read_csv()..."),
list(role = "user", content = "What's the difference between them?")
)
response <- create_chat_completion(
model = "gpt-5.4-mini",
messages = messages
)Available Models
GPT-5 Series (Latest)
| Model | Best For | Cost |
|---|---|---|
gpt-5.4 |
Complex reasoning, coding | Higher |
gpt-5.4-mini |
Fast, everyday tasks | Medium |
gpt-5.4-nano |
Lowest latency, budget | Lower |
O-Series (Reasoning Models)
| Model | Best For | Cost |
|---|---|---|
o3 |
Most powerful reasoning | Highest |
o3-mini |
Balanced reasoning | Medium |
o4-mini |
Affordable reasoning | Lower |
Legacy Models (still available in API)
| Model | Notes |
|---|---|
gpt-4o |
Retired from ChatGPT Feb 2026, API still available |
gpt-4-turbo |
128k context |
# List available models
models <- list_models()Control Response Parameters
Temperature (creativity)
# More deterministic (good for code)
create_chat_completion(
model = "gpt-5.4-mini",
messages = list(list(role = "user", content = "Write R code to calculate mean")),
temperature = 0.2
)
# More creative (good for brainstorming)
create_chat_completion(
model = "gpt-5.4-mini",
messages = list(list(role = "user", content = "Suggest project ideas")),
temperature = 0.9
)Limit response length
response <- create_chat_completion(
model = "gpt-5.4-mini",
messages = list(list(role = "user", content = "Explain ggplot2")),
max_tokens = 150 # Limit response length
)Practical Examples
Generate R code
Use a system prompt to get code-only responses:
prompt <- "Write R code to:
1. Load the mtcars dataset
2. Calculate average mpg by cylinder count
3. Create a bar chart of the results"Set low temperature for deterministic code:
response <- create_chat_completion(
model = "gpt-5.4",
messages = list(
list(role = "system", content = "Return only R code, no explanations."),
list(role = "user", content = prompt)
),
temperature = 0.2
)
cat(response$choices[[1]]$message$content)Analyze text data
Create a reusable sentiment classifier. For more robust extraction, see How to Extract Structured Data with LLMs.
analyze_sentiment <- function(text) {
response <- create_chat_completion(
model = "gpt-5.4-mini",
messages = list(
list(role = "system", content = "Classify as positive/negative/neutral. One word only."),
list(role = "user", content = text)
),
temperature = 0
)
response$choices[[1]]$message$content
}Apply to multiple reviews:
reviews <- c("Great product!", "Terrible quality", "It's okay")
sapply(reviews, analyze_sentiment)
# "positive", "negative", "neutral"Summarize text
long_text <- "Your long document here..."
response <- create_chat_completion(
model = "gpt-5.4-mini",
messages = list(
list(role = "system", content = "Summarize the following text in 2-3 sentences."),
list(role = "user", content = long_text)
)
)Using httr2 Directly
For more control, call the API directly with httr2.
Build the request
library(httr2)
response <- request("https://api.openai.com/v1/chat/completions") |>
req_headers(
Authorization = paste("Bearer", Sys.getenv("OPENAI_API_KEY")),
`Content-Type` = "application/json"
) |>
req_body_json(list(
model = "gpt-5.4-mini",
messages = list(list(role = "user", content = "Hello!"))
)) |>
req_perform() |>
resp_body_json()Extract the response
response$choices[[1]]$message$contentError Handling
safe_completion <- function(prompt) {
tryCatch({
response <- create_chat_completion(
model = "gpt-5.4-mini",
messages = list(list(role = "user", content = prompt))
)
response$choices[[1]]$message$content
}, error = function(e) {
message("API Error: ", e$message)
NA
})
}
# Use safely
result <- safe_completion("What is 2+2?")Common errors
| Error | Cause | Solution |
|---|---|---|
| 401 Unauthorized | Invalid API key | Check OPENAI_API_KEY |
| 429 Rate limit | Too many requests | Add delays between calls |
| 400 Bad request | Invalid parameters | Check model name, messages format |
Cost Management
Understand tokens
# Rough estimate: 1 token ≈ 4 characters in English
# "Hello, how are you?" ≈ 6 tokens
# Check usage in response
response <- create_chat_completion(
model = "gpt-5.4-mini",
messages = list(list(role = "user", content = "Hi"))
)
response$usage
# $prompt_tokens: 9
# $completion_tokens: 10
# $total_tokens: 19Limit costs
# Use cheaper models for simple tasks
create_chat_completion(
model = "gpt-5.4-mini", # Cheaper than gpt-4o
messages = list(list(role = "user", content = prompt)),
max_tokens = 100 # Limit response length
)Batch Processing
Process multiple items efficiently:
library(purrr)
texts <- c("Text 1", "Text 2", "Text 3")
# Add delay to avoid rate limits
results <- map(texts, \(text) {
Sys.sleep(0.5) # 500ms delay
response <- create_chat_completion(
model = "gpt-5.4-mini",
messages = list(
list(role = "user", content = paste("Summarize:", text))
)
)
response$choices[[1]]$message$content
})Alternative: ellmer Package
The tidyverse-friendly alternative:
install.packages("ellmer")
library(ellmer)
chat <- chat_openai(model = "gpt-5.4-mini")
chat$chat("What is R programming?")See our ellmer tutorial for more details.
Common Mistakes
1. Forgetting to set API key
# Check if key is set
Sys.getenv("OPENAI_API_KEY")
# Should not be empty2. Not handling rate limits
# Add delays in loops
for (item in items) {
result <- create_chat_completion(...)
Sys.sleep(1) # Wait 1 second
}3. Using expensive models for simple tasks
# gpt-5.4-mini is often sufficient and much cheaper
# Only use gpt-5.4 or o3 for complex reasoning tasks4. Not checking response structure
# Always verify the response has expected content
if (!is.null(response$choices[[1]]$message$content)) {
result <- response$choices[[1]]$message$content
}Summary
| Task | Code |
|---|---|
| Basic completion | create_chat_completion(model, messages) |
| Set API key | Sys.setenv(OPENAI_API_KEY = "key") |
| Control creativity | temperature = 0.2 (low) to 0.9 (high) |
| Limit response | max_tokens = 100 |
| Check usage | response$usage$total_tokens |
- Start with
gpt-5.4-minifor cost efficiency - Use
o3oro3-minifor complex reasoning tasks - Use low temperature for deterministic outputs
- Add delays when processing multiple items
- Always handle errors gracefully