PHP
PHP has no first-party OpenAI SDK. This page uses openai-php/client, the
community-maintained library most PHP projects standardise on. It is configured
through a factory, so routing through the firewall is two calls — withBaseUri and
withApiKey. Everything else about your code stays the same, and the provider key
stays in the vault.
Install
composer require openai-php/client
Configure
<?php
use OpenAI;
$org = getenv('VULNETIX_ORG_UUID');
$client = OpenAI::factory()
->withApiKey(getenv('VULNETIX_API_KEY')) // Vulnetix key, not an OpenAI key
->withBaseUri("guardrails.vulnetix.com/openai/{$org}/v1")
->make();
$result = $client->chat()->create([
'model' => 'gpt-4o-mini',
'messages' => [
['role' => 'user', 'content' => 'Hello'],
],
]);
echo $result->choices[0]->message->content;
Swap openai in the path for any other provider slug and pass that provider’s own
model string — the gateway forwards model verbatim.
Streaming
Unchanged. The gateway relays the provider’s SSE stream.
$stream = $client->chat()->createStreamed([
'model' => 'gpt-4o-mini',
'messages' => [['role' => 'user', 'content' => 'Hello']],
]);
foreach ($stream as $response) {
echo $response->choices[0]->delta->content ?? '';
}
Handling a guardrail block
A request your policy refuses never reaches the provider. It returns an
OpenAI-shaped 403, which the client throws as
OpenAI\Exceptions\ErrorException.
use OpenAI\Exceptions\ErrorException;
try {
$result = $client->chat()->create([
'model' => 'gpt-4o-mini',
'messages' => [['role' => 'user', 'content' => $prompt]],
]);
} catch (ErrorException $e) {
// getErrorCode() is the `code` field from the firewall's error body.
if ($e->getErrorCode() === 'request_blocked') {
throw new RuntimeException(
'AI firewall blocked this request: ' . $e->getErrorMessage(),
previous: $e,
);
}
throw $e; // provider_denied, model_denied, model_not_allowed, provider_key_missing
}
getErrorCode() is what tells your organisation refused this apart from the
provider refused this:
code | Meaning |
|---|---|
request_blocked | A content guardrail matched. The message names the rule. |
provider_denied | Policy does not allow this provider. |
model_denied / model_not_allowed | Policy does not allow this model. |
provider_key_missing | No provider key in the vault for this provider. |
The exception exposes the standard OpenAI error fields — getErrorMessage(),
getErrorCode(), getErrorType() — but not Vulnetix’s blocked_by and
violations. The rule name is also in the message text; if you need the structured
fields, call the endpoint with your own HTTP client and read the body. See
curl & raw HTTP for the exact envelope.
pii_redact rule rewrites the
matched spans in your prompt to the literal [REDACTED] and forwards the request.
You get an ordinary completion back, about redacted text.Tool / function calling
Tools are forwarded untouched. Guardrails inspect the request you send, which includes the tool-result messages you append before the next call.
Gotchas
withApiKeytakes your Vulnetix key. An OpenAI key here is the most common401.withBaseUrifollows the library’s convention of a host-and-path string with no scheme (guardrails.vulnetix.com/openai/{org}/v1); it defaults to HTTPS. Keep the/v1suffix.- This is a community library. If your project uses a different PHP client, the two
settings are the same — find its base-URI and API-key options, and make sure the
request lands on
…/{orgUuid}/v1/chat/completions.