Artificial intelligence is becoming a useful addition to modern PHP applications. You can use AI to generate text, summarize documents, answer questions, classify content, and automate repetitive tasks.
But how can a regular PHP application communicate with an AI model?
The basic idea is simple. PHP sends an HTTP request to an AI provider, the provider processes the request, and PHP reads the response.
In this tutorial, we'll use PHP cURL to call the OpenAI Responses API. We'll cover API authentication, request handling, response parsing, and common errors.
You don't need Laravel or Symfony for this example. Plain PHP is enough.
What do you need?
Before starting, make sure you have:
- PHP 8.1 or later.
- The PHP cURL extension enabled.
- An API key with access to the model you intend to use.
- Internet access from the machine running PHP.
Important: API usage may incur separate charges. A ChatGPT subscription does not automatically include API usage.
Step 1: Configure your API key
Never hardcode a real API key in your PHP source code. If you publish the file or commit it to a public Git repository, somebody else could use the key.
Instead, store the key in an environment variable named OPENAI_API_KEY.
For a temporary Linux or macOS terminal session, run:
export OPENAI_API_KEY='your_api_key_here'
Replace the placeholder with your actual key. Do not include the key in a public tutorial, screenshot, or repository.
Your PHP process must be able to read this environment variable. On shared hosting, use the hosting provider's supported environment-variable or secret-management feature.
Step 2: Create the PHP API request
Create a file named ai_request.php.
The following example sends a prompt to the Responses API and prints the generated text.
<?php
declare(strict_types=1);
$apiKey = getenv('OPENAI_API_KEY');
if (!is_string($apiKey) || $apiKey === '') {
fwrite(STDERR, "Missing OPENAI_API_KEY environment variable.\n");
exit(1);
}
if (!function_exists('curl_init')) {
fwrite(STDERR, "The PHP cURL extension is not enabled.\n");
exit(1);
}
$payload = [
'model' => 'gpt-4.1-mini',
'input' => 'Explain what PHP cURL does in two short sentences.',
];
try {
$jsonPayload = json_encode(
$payload,
JSON_THROW_ON_ERROR
);
} catch (JsonException $e) {
error_log('Could not encode AI API request JSON.');
fwrite(STDERR, "Could not prepare the API request.\n");
exit(1);
}
$ch = curl_init(
'https://api.openai.com/v1/responses'
);
if ($ch === false) {
fwrite(STDERR, "Could not initialize cURL.\n");
exit(1);
}
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $jsonPayload,
]);
$body = curl_exec($ch);
$curlError = $body === false
? curl_error($ch)
: null;
$statusCode = (int) curl_getinfo(
$ch,
CURLINFO_HTTP_CODE
);
curl_close($ch);
if ($body === false) {
error_log('AI API transport error: ' . $curlError);
fwrite(
STDERR,
"Could not reach the AI API. Check the server logs and network.\n"
);
exit(1);
}
try {
$data = json_decode(
$body,
true,
512,
JSON_THROW_ON_ERROR
);
} catch (JsonException $e) {
error_log(
'AI API returned invalid JSON (HTTP ' . $statusCode . ').'
);
fwrite(
STDERR,
"The AI provider returned an invalid response.\n"
);
exit(1);
}
if ($statusCode < 200 || $statusCode >= 300) {
error_log('AI API returned HTTP status ' . $statusCode);
fwrite(
STDERR,
"The AI provider returned HTTP status {$statusCode}. Check server logs.\n"
);
exit(1);
}
if (!is_array($data)) {
fwrite(
STDERR,
"The AI provider returned an unexpected response structure.\n"
);
exit(1);
}
$textParts = [];
foreach (($data['output'] ?? []) as $outputItem) {
foreach (($outputItem['content'] ?? []) as $contentItem) {
if (
($contentItem['type'] ?? null) === 'output_text'
&& isset($contentItem['text'])
&& is_string($contentItem['text'])
) {
$textParts[] = $contentItem['text'];
}
}
}
$answer = trim(implode("\n", $textParts));
if ($answer === '') {
fwrite(
STDERR,
"No text output was found in the API response.\n"
);
exit(1);
}
echo $answer . PHP_EOL;
The example uses the OpenAI Responses API. Confirm that the selected model is available to your API project before running the script.
Step 3: Run the script
Open a terminal in the directory containing ai_request.php and execute:
php ai_request.php
If the request succeeds, the terminal should display a short explanation of PHP cURL.
The exact response will vary because the text is generated dynamically.
Step 4: Understand the important parts
1. The API endpoint
https://api.openai.com/v1/responses
This is the endpoint used by the example. The PHP script sends a POST request containing JSON.
2. Authentication
'Authorization: Bearer ' . $apiKey
The API key authenticates the request. Reading the key from the environment keeps it out of the source code.
3. JSON encoding
$jsonPayload = json_encode(
$payload,
JSON_THROW_ON_ERROR
);
The request body must be valid JSON. Using JSON_THROW_ON_ERROR ensures that PHP reports an encoding failure instead of silently returning an unexpected value.
4. Request timeouts
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 60,
The connection timeout limits how long cURL waits to establish a connection. The overall timeout limits how long the complete request can take.
Without sensible timeouts, a slow or unreachable service can leave your application waiting too long.
5. HTTP status checking
A request can reach the server successfully but still receive an error such as HTTP 401, 403, or 429.
That's why the script checks the HTTP status separately from the cURL transport result.
6. Response parsing
The API returns a structured response. The script searches the output array for content items of type output_text instead of assuming that generated text always appears at one fixed array position.
This makes the example more robust when the response contains multiple output items.
Step 5: Common errors and solutions
| Error | What to check |
|---|---|
| Missing API key | Confirm the environment variable is available to the PHP process. |
| HTTP 401 | Verify the API key and project configuration. |
| HTTP 403 | Check permissions and model access. |
| HTTP 429 | Review rate limits and usage or billing limits. |
| cURL connection error | Check DNS, outbound HTTPS access, and TLS configuration. |
| Request timeout | Check network latency and whether the request needs a different timeout. |
| Invalid JSON response | Inspect a safe diagnostic in your server logs and verify the endpoint response. |
| No text output | Handle responses that contain no ordinary text, including refusals or other output types. |
Do not expose raw provider error messages or internal diagnostics to website visitors. Log useful details on the server without logging API keys or sensitive user data.
Step 6: Security considerations
Before using this integration on a live website, remember these points:
- Never expose the API key in frontend JavaScript.
- Add authentication and rate limiting if visitors can trigger API requests.
- Limit prompt length to control costs and prevent abuse.
- Avoid logging private prompts or sensitive responses unnecessarily.
- Escape generated text before displaying it as HTML.
- Add monitoring and usage limits appropriate to your application.
AI output is not automatically safe or accurate just because it comes from an API.
Conclusion
PHP cURL gives you a straightforward way to integrate AI into an existing PHP application without installing a framework.
The important steps are to configure credentials safely, send a valid JSON request, check transport and HTTP errors, and parse the response carefully.
You can reuse these fundamentals when building AI-powered chatbots, text summarizers, content classifiers, document assistants, and semantic search features.
In the next tutorial, we'll explore how to build a simple AI chatbot using core PHP.
Frequently asked questions
Can I call an AI API using core PHP?
Yes. PHP cURL can send HTTP requests directly to an AI provider. You don't need Laravel or Symfony for a basic integration.
Do I need Composer?
Not for this example. It uses PHP's built-in cURL extension rather than a third-party SDK.
Can I use another AI provider?
Yes. The general approach is similar, but each provider may use a different endpoint, authentication scheme, request format, and response structure.
Can I use this code in production?
Treat it as a starting point. Before deploying it, test the live API request and error paths, add application-level authentication and rate limiting, and review your logging and cost controls.
Official references
- OpenAI API documentation: https://platform.openai.com/docs
- PHP cURL documentation: https://www.php.net/manual/en/book.curl.php
- PHP JSON documentation: https://www.php.net/manual/en/book.json.php
0 comments:
Post a Comment