Skip to content

Add Zotniq to OpenAI

Prereqs: Python 3.9+ · OpenAI API key · Zotniq API key (optional for local mode) Time to first call: ~30 seconds

Zotniq wraps the OpenAI SDK so every user message is checked against your team's rules before it leaves your machine. PII is masked in place; blocked prompts never reach OpenAI, so no tokens are burned.


1. Install

pip install zotniq[openai]

Installs zotniq and the openai client together.


2. Configure

Two environment variables:

export ZOTNIQ_API_KEY=zot_sk_...      # optional — omit for local mode
export OPENAI_API_KEY=sk-...

Skip ZOTNIQ_API_KEY for local mode

Without a Zotniq key the wrapper still runs full local detection and masking. Cloud mode adds server-side rules and an audit trail at app.zotniq.ai.


3. Run

import os
from zotniq import Zotniq
from zotniq.integrations.openai import wrap_openai

client = wrap_openai(
    Zotniq(api_key=os.environ.get("ZOTNIQ_API_KEY")),
    api_key=os.environ["OPENAI_API_KEY"],
)

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "user", "content": "Summarize: my SSN is 123-45-6789."},
    ],
)
print(response.choices[0].message.content)

4. What you should see

The SSN is masked to XXX-XX-6789 before OpenAI receives it. OpenAI's response summarizes the masked prompt. Your audit row in the Zotniq dashboard records the decision ALLOWED_WITH_MASKING with the detection type SSN.

If you send a payload with PHI (patient names, diagnoses, MRN), the decision becomes BLOCKED and the wrapper returns a synthetic ChatCompletion-shaped refusal without calling OpenAI. Check for it with:

if response.system_fingerprint == "zotniq_blocked":
    reason = response.choices[0].message.content
    # route to human reviewer, log, or surface to the user

Behavior reference

Decision Wrapper action
ALLOWED User message forwarded to OpenAI unchanged.
ALLOWED_WITH_MASKING User message rewritten to result.masked_text before send.
BLOCKED No OpenAI call. Returns synthetic response with the refusal in choices[0].message.content and system_fingerprint="zotniq_blocked".

Only the last user message in each request is preflight-checked. History messages are assumed to have been checked when they were originally added.


Troubleshooting

ImportError: openai package is required

Install the extra: pip install zotniq[openai].

AuthError from Zotniq

ZOTNIQ_API_KEY is set but invalid. Generate a fresh key at app.zotniq.ai → Settings → API Keys.

OpenAI 401

OPENAI_API_KEY is missing or invalid. This is an OpenAI-side error; Zotniq forwarded successfully.


Next