Skip to content

API endpoints reference

Package: piighost-api

piighost-api serve builds one thread pipeline from its configuration. Every route below goes through that pipeline. Request and response bodies are JSON. The OpenAPI schema is served at /schema/openapi.json, with a Swagger UI at /schema/swagger. PIIGhostClient calls the pipeline routes, see Remote client.


Authentication

The server loads its keys at start from every environment variable whose name starts with API_KEY_. A protected route then requires the header Authorization: Bearer <key>.

RoutesKey required
GET /, GET /health, GET /v1/labelsnever
/v1/detect, /v1/anonymize, /v1/anonymize/corrected, /v1/deanonymize, /v1/threads/..., /schema/...when keys are loaded
/openai/v1/..., /anthropic/v1/...never, the caller's credentials are relayed to the upstream

A missing or malformed header answers 401 with Missing or malformed Authorization header. An unknown key answers 401 with Invalid API key. When no key loads, the server refuses to start, unless PIIGHOST_ALLOW_ANONYMOUS is set. In that case, no route asks for a key. The variables are listed in Server CLI.


Status codes

StatusWhen
200a GET or DELETE route succeeds
201a POST pipeline route succeeds
400the body fails validation, a proxy body is not a JSON object, or a proxy request names no upstream and none is configured
401a protected route gets no valid key
404the route does not exist, under the proxy prefixes too
413the body exceeds PIIGHOST_MAX_BODY_BYTES
429the client exceeds PIIGHOST_RATE_LIMIT, with RateLimit-* headers
500the pipeline raises, a guard flagging a value left in clear or an unknown role among others
502a proxy route cannot reach its upstream

A proxy route otherwise answers with the upstream's status.


Shared objects

Entity

FieldTypeDescription
labelstringThe entity label, such as PERSON
placeholderstringThe token that replaces the entity, empty on /v1/detect
detectionslist of DetectionEvery occurrence of the entity in the text

Detection

FieldTypeDescription
textstringThe value as it appears in the text
labelstringThe detection label
start_posintegerStart offset in the text
end_posintegerEnd offset in the text, exclusive
confidencefloatDetector score, 1.0 for a regex or an exact match

Service routes

GET /

{"name": "piighost-api", "version": "...", "docs": "/schema/swagger"}

version is the installed piighost-api version.

GET /health

{"status": "ok", "detector": "composite"}

detector is the type of the configuration's [detector] section. GET / and GET /health are exempt from PIIGHOST_RATE_LIMIT.

GET /v1/labels

{"name": "piighost/fr-default:e6990159", "detector": "regex", "labels": ["CREDIT_CARD", "EMAIL", "EU_VAT", "FR_IBAN", "FR_NIR", "FR_PHONE", "FR_SIREN", "FR_SIRET", "IBAN", "IPV4", "SWIFT_BIC", "URL"]}
FieldTypeDescription
namestring or nullThe configuration's name
detectorstringThe type of [detector]
labelslist of stringsEvery label [detector] can emit, sorted

The labels are collected from the [detector] section alone, the guard's detector excluded.

Detector typeLabels
regexthe keys of patterns, plus those of every catalog group in catalogs, read from the catalog through its disk cache
gliner2, spacy, transformers, llmlabels, or its keys when it maps model labels to canonical ones
exactthe labels of values
compositethe union of its detectors
chunkedthose of its detector
any othernone

Pipeline routes

POST /v1/detect

Runs the detector and the linker on a text and returns the entities, without placeholders. The thread memory is neither read nor written, and the override, overlap, expansion and guard stages do not run.

Request fieldTypeDefault
textstringrequired
thread_idstring"default", accepted and unused

For the text Write to jane.doe@example.com, the response reads:

{"entities": [{"label": "EMAIL", "placeholder": "", "detections": [{"text": "jane.doe@example.com", "label": "EMAIL", "start_pos": 9, "end_pos": 29, "confidence": 1.0}]}]}

POST /v1/anonymize

De-identifies a message in a thread, with tokens consistent across the thread.

Request fieldTypeDefault
textstringrequired
thread_idstringrequired
role"user" or "assistant""user"
Response fieldTypeDescription
anonymized_textstringThe text with each value replaced by its placeholder
entitieslist of EntityThe entities of this message that received a token

role tells who wrote the message, and therefore who introduced the values it brings in. A value first written by the assistant gets no token and stays in clear.

POST /v1/anonymize/corrected

De-identifies a message again from a corrected detection set, for a human review step. The corrected set goes through the configured override, then replaces the message's detections in the thread memory. Detection does not run again.

Request fieldTypeDefault
textstringrequired
detectionslist of objects with text, label, start, end, confidencerequired
thread_idstringrequired

A corrected detection names its offsets start and end, not start_pos and end_pos. The response is {"anonymized_text": "..."}.

POST /v1/deanonymize

Restores every placeholder the thread issued, in any text, a model reply included. A token the thread never issued stays as it stands.

Request fieldTypeDefault
textstringrequired
thread_idstringrequired

The response is {"text": "..."}.

GET /v1/threads/{thread_id}/tokens

Returns the thread's placeholder-to-value map, for a client that restores a stream itself.

{"tokens": {"<<PERSON:1>>": "Jane Doe", "<<EMAIL:1>>": "jane.doe@example.com"}}

DELETE /v1/threads/{thread_id}

Erases the thread from the memory and reports what was dropped. A thread that does not exist reports zero.

{"messages": 1, "detections": 2}

OpenAI-compatible proxy

Prefix: /openai/v1

Request headerEffect
X-PIIGhost-UpstreamBase URL of the upstream, PIIGHOST_OPENAI_UPSTREAM when absent
X-PIIGhost-Thread-IdFixed thread kept after the request. When absent, each request gets a fresh thread, forgotten once the reply is restored

Only Authorization, Content-Type, x-api-key, anthropic-version and anthropic-beta are relayed to the upstream.

RouteDe-identified in the requestRestored in the reply
POST /chat/completionsmessages[].content, a string or the text of each part, and every string inside messages[].tool_calls[].function.argumentschoices[].message.content and choices[].message.tool_calls[].function.arguments, or choices[].delta.content when streamed
POST /completionsprompt, suffixchoices[].text
POST /embeddingsinputnothing
POST /moderationsinputnothing
GET /models, GET /models/{model}relayed as isrelayed as is
POST /images/generations, /images/edits, /images/variationsrelayed as isrelayed as is
POST /audio/speech, /audio/transcriptions, /audio/translationsrelayed as isrelayed as is
  • A successful JSON reply is restored. Any other reply is relayed as is, with the upstream status. The upstream's response headers are not relayed.
  • Query parameters reach the upstream on the routes relayed as is only.
  • A streamed chat/completions request is answered 201 before the upstream answers, so an upstream error arrives inside the stream body.
  • The upstream timeout is 60 seconds.

Anthropic-compatible proxy

Prefix: /anthropic/v1

Request headerEffect
X-PIIGhost-UpstreamBase URL of the upstream, PIIGHOST_ANTHROPIC_UPSTREAM when absent
X-PIIGhost-Thread-IdFixed thread kept after the request. When absent, each request gets a fresh thread, forgotten once the reply is restored

Every request header is relayed except the hop-by-hop ones (Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, TE, Trailer, Transfer-Encoding, Upgrade), Host, Content-Length, Accept-Encoding and any X-PIIGhost-* header. Query parameters are relayed.

RouteDe-identified in the requestRestored in the reply
POST /messagesmessages[].content, a string or its text, tool_use and tool_result blocks, plus system when PIIGHOST_ANTHROPIC_ANONYMIZE_SYSTEM is onthe text, tool_use and tool_result blocks of content, or the text_delta and input_json_delta of each content_block_delta event when streamed
POST /messages/count_tokenssame as /messagesnothing, the count is relayed
  • Every string inside a tool_use input is rewritten. The other blocks, an image or a document among them, are relayed untouched, and so are the tools definitions.
  • The guidance note set by PIIGHOST_ANTHROPIC_PLACEHOLDER_NOTE is prepended after de-identification. Depending on PIIGHOST_ANTHROPIC_NOTE_PLACEMENT, it goes at the head of the system prompt or of the first user message.
  • The reply keeps the upstream status. It also keeps the upstream's response headers, retry-after and anthropic-ratelimit-* included, except the length, encoding, connection and content-type ones.
  • A streamed request the upstream refuses is answered with the upstream status as a plain response. An accepted one streams with 200.
  • The upstream timeout is 60 seconds.

See also