Privaro API v0.3.0
Privaro is a runtime data governance layer that sits between your application
(or agents) and any LLM provider. It detects personal/sensitive data, replaces
it with reversible tokens, and lets you re-identify the original values safely
outside the model.
**Source of truth for this spec:** the actual FastAPI source code of
`privaro-proxy` (app/routers/*.py, app/models/schemas.py, app/services/auth.py),
read directly from the repository — not inferred from README documentation.
Field names, request/response shapes and auth are taken verbatim from the
Pydantic models. This is the full, real endpoint surface: 17 endpoints across
four routers (Proxy, Relay, Agent, Image/Document).
Servers
https://api.privaro.ai/v1 Production
17 endpoints
POST /proxy/detect
Detect PII without masking (analysis mode)
Runs detection only — does not tokenize, mask, or persist anything. Useful for a dry-run risk check.
Tags: Proxy
Responses
200 Detections found (nothing modified or stored).401 403 404
POST /proxy/protect
Detect + tokenize PII in a prompt (core endpoint)
Detects PII, tokenizes it per policy, persists an audit log and (if options.reversible, the default) a reversible token vault entry. Because tokens are not unique across unrelated requests over time, conversation_id is REQUIRED whenever options.reversible is true (the default) — pass options.reversible=false to make it optional. Fails open (returns the original, unmodified prompt with degraded_mode=true) rather than 500 on an internal detector timeout/error.
Tags: Proxy
Responses
200 Prompt scanned and tokenized (or passed through unmodified in degraded_mode).401 403 404 422 Validation error — most commonly a missing conversation_id while options.reversible is true, or an invalid (non-UUID) conversation_id.
POST /proxy/protect-output
Scan an LLM response for leaked/hallucinated PII (output direction)
For customers who call /proxy/protect themselves and then make their OWN LLM call elsewhere (as opposed to /relay/complete, where Privaro makes the call and scans it inline). Requires the pipeline to have output scanning enabled (dashboard: Pipelines → Settings → Output scanning) — returns 403 otherwise.
Tags: Proxy
Responses
200 Response scanned.401 403 Output scanning is not enabled for this pipeline (or org mismatch).404
POST /proxy/detokenize
Bulk, automated reversal of every Privaro token found in a text
Finds every [XX-0001]-style token in `text` and reverses all of them in one call — for agentic write-back flows (e.g. an ERP copilot writing a real value back to a database) as opposed to a human manually revealing one token at a time in the dashboard. Strictly scoped to the caller's own org and to the given conversation_id — tokens outside that scope are reported in tokens_not_found, never silently substituted from elsewhere.
Tags: Proxy
Responses
200 Reversal complete (partial matches are normal — see tokens_not_found).401 403 404
POST /proxy/protect-structured
Field-aware protection for structured/typed payloads
For structured records (e.g. ERP/CRM rows) rather than free text. A field's NAME can force its entity_type via a policy rule (field_name_pattern) even if the value's content wouldn't otherwise match any pattern — e.g. a field literally named "diagnostico" is treated as health data regardless of its content. conversation_id is always required here (every tokenized value is persisted).
Tags: Proxy
Responses
200 Each field protected independently.400 fields must not be empty.401 403 404
POST /proxy/protect-document
Protect a whole document before RAG ingestion
Protects an entire document BEFORE it's chunked and embedded into a vector store, so PII never sits in the vector DB or an embedding in plain text. Chunking happens AFTER tokenization. Documents above a size threshold are processed asynchronously — the response comes back with status="processing" and a job_id to poll instead of the full result. Does not support optimize_context (Kompress can crash on large inputs).
Tags: Proxy
Responses
200 Either the completed result, or a job_id if processing async (large documents).401 403 404
GET /proxy/protect-document/{job_id}
Poll the status of an async document ingestion job
Scoped to the caller's own org — a job belonging to another org returns 404, never leaks existence.
Tags: Proxy
Parameters
Responses
200 Job status (processing | completed | failed).401 404 Job not found for this org.
POST /proxy/protect-retrieval
Protect a batch of retrieved RAG chunks, with per-chunk access control
Defense-in-depth right before retrieved chunks enter an LLM's context — catches PII that slipped past ingestion, and can block chunks the requester isn't authorized to see (via each chunk's allowed_roles). Results are cached by content hash per org, since this sits on the hot path of every RAG query. A per-chunk detection failure fails CLOSED (blocked, not passed through) — unlike /protect-document, which fails open for the whole document.
Tags: Proxy
Responses
200 Chunks split into allowed (protected) and blocked (access-denied or failed).401 403 404
POST /proxy/protect-image-document
OCR + PII protection for a photographed/scanned document
Accepts an image (DNI, contract, screenshot), OCRs it with Tesseract, runs the same detection/policy engine as /proxy/protect, and returns both the protected text and (by default) a redacted copy of the image with PII regions blacked out. Tier-1 OCR only (Tesseract) as of this version — accuracy on real phone photos, not just clean scans, is still being measured (see ocr_quality in the response).
Tags: Document
Responses
200 Full protection result, or (if extract_only=true) just the raw extracted text and OCR quality stats.
401 413 File exceeds the 15MB limit.422 OCR found no readable text in the image.
GET /proxy/test
Health check with a live sample detection
Runs a fixed sample string through the hybrid detector (regex + NLP) and returns the result — useful to confirm both detector tiers are active.
Tags: Proxy
Responses
200 Detector status and a sample detection.
POST /relay/complete
Protect + call your configured LLM + de-tokenize the response
Full-cycle relay: protects every message, calls the LLM configured for the pipeline (customer's own provider key, set at /app/admin/providers, decrypted only at request time), then de-tokenizes the response before returning it. If the pipeline has output_scanning_enabled, also scans the raw LLM response for newly-introduced PII (RAG leakage, model memorization) before de-tokenizing.
Tags: Relay
Responses
200 LLM call completed; response de-tokenized.401 403 404 502 llm_provider_error — the configured LLM call failed. Check /app/admin/providers.
POST /relay/stream
Streaming version of /relay/complete (SSE)
Same contract as /relay/complete but streams de-tokenized text deltas as Server-Sent Events. Buffers internally to never split a [XX-0001] token across two chunks. Gated by organizations.streaming_enabled (403 if disabled for the org). Output-direction scanning here is audit-only (post-hoc) — by the time a full response could be scanned, every chunk has already been delivered to the client, so "enforce" mode cannot mask anything retroactively; detections are logged with action="leaked" in that case rather than silently downgraded.
Tags: Relay
Responses
200 text/event-stream of {"delta": "..."} chunks, ending with "[DONE]".401 403 Streaming is disabled for this organization — use /relay/complete instead.
GET /relay/providers
List supported LLM providers and their available models
Tags: Relay
Responses
POST /agent/run/start
Start a multi-step agent run
Opens an agent_run_id that scopes token consistency across the following /agent/protect and /agent/reveal calls (e.g. a LangChain or CrewAI agent with several tool/LLM steps).
Tags: Agent
Responses
200 Agent run created.401 403 404
POST /agent/protect
Protect a step within an active agent run
Accepts one or more messages for this step (a prompt, tool outputs, observations). Same PII value maps to the same token throughout the whole run. Messages with role in (assistant, tool) or step_type in (tool_output, observation) are evaluated as direction=output against policy (so an org's output-scoped rules can fire on them); user/system messages are direction=input.
Tags: Agent
Responses
200 Step protected.401 404 agent_run_not_found.409 agent_run_not_active (the run was already ended).
POST /agent/reveal
Detokenize text using the token map of an agent run
Fetches every reversible token created within this agent_run_id, decrypts (AES-256-GCM), and replaces every [TYPE-XXXX] token found in `text` with its real value.
Tags: Agent
Responses
200 Tokens resolved.401 404 agent_run_not_found.
POST /agent/run/end
Close an agent run and finalize its counters
Tags: Agent
Responses
200 Run closed.401 404 agent_run_not_found.