API Overview Beta
The Privshot API lets you detect and redact personally identifiable information (PII) from images programmatically. Send an image, get back bounding boxes or a clean redacted PNG — your choice.
All requests go to https://privshot.com/api/v1. The API accepts multipart/form-data uploads and responds with JSON or binary PNG depending on the endpoint.
score and a review_recommended flag (see Detection quality & review) — gate on them for anything sensitive. Where the API is strongest today: structured identifiers (IBAN, credit cards, SSN and other national IDs) are matched by checksum-validated patterns and are highly reliable; free-text names and addresses depend on OCR + NLP and are more likely to be missed.
Interactive preview
See how each option changes the output on a sample screenshot — the preview runs entirely in your browser on pre-detected regions, so it costs no credits and needs no API key.
#000000✓ Paid-plan options are active in this preview.
Preview only · runs in your browser · no credits used.
Equivalent request
Authentication
Pass your API key in the X-Api-Key header with every request.
You can create and manage API keys from your dashboard. Keys start with ps_.
Errors
All errors return a JSON body with an error field describing the problem.
| HTTP status | Meaning |
|---|---|
400 | Bad request — missing/invalid file, or an invalid option value |
401 | Missing or invalid API key |
402 | Insufficient credits (paid tier only) |
403 | Email not verified, or a paid-only option used on a free request |
409 | A request with the same Idempotency-Key is already in progress |
429 | Rate limit or daily quota exceeded |
500 | Internal server error — please retry |
GET /health
Check that the API is reachable. No authentication required.
Response
GET /entities
List the entity types, languages and region scopes the engine supports. Use the entities values for the entities/allow options, the languages for language, and the regions for region. No authentication required.
Response
POST /analyze
Detect PII in an image and return bounding boxes with entity labels. The original image is not modified — this is a read-only detection call.
Request
| Field | Type | Description |
|---|---|---|
file required | File | Image to analyze. PNG, JPEG, or WEBP. Max 20 MB. |
entities optional | String | Comma-separated entity types to detect. Defaults to all. See Redaction options. |
allow optional | String | Comma-separated entity types to exclude from the result. |
min_confidence optional | Number | Minimum detection confidence, 0–1 (default 0.4). |
language optional | String | OCR + name/location language (default en). See options. |
region optional | String | Country/region scope for national IDs (e.g. fr, eu). See Region scopes. |
Send an Idempotency-Key header to make retries safe (see Idempotency).
Example
Response
Coordinates (x, y, w, h) are in pixels relative to the original image dimensions. Each box carries a score (0–1 detection confidence); the top-level regions_count, min_confidence_found and review_recommended summarise the result — see Detection quality & review.
POST /redact
Detect PII and return a redacted image with all sensitive regions obscured. Supports JSON (base64) or raw binary PNG output, plus the redaction options below.
Request
| Field | Type | Description |
|---|---|---|
file required | File | Image to redact. PNG, JPEG, or WEBP. Max 20 MB. |
format optional | String | json (default) or binary for a raw PNG stream. |
entities, allow, min_confidence free | String / Number | Same as /analyze. Control what gets detected and redacted. |
language, region free | String | Same as /analyze. Language and country/region scope. |
color free | String | Hex fill colour for boxes, e.g. #ff0000 (default black). |
style paid | String | box (default), blur, or pixelate. |
padding paid | Integer | Expand each redacted region by N pixels (0–100). |
show_labels paid | Boolean | Stamp the entity type above each region. |
style blur/pixelate, padding, show_labels) return 403 on a free request. Basic options work on every tier.
Examples
Binary PNG, blur style, keep names visible
JSON response
binary responses carry the same signal as headers: X-Regions-Count and X-Review-Recommended. For per-region scores, call /analyze.
Redaction options
Options are sent as extra multipart/form-data fields (or query parameters) alongside the file. They apply to both /analyze and /redact where relevant.
| Option | Tier | Values | Effect |
|---|---|---|---|
entities | Free | comma list | Detect only these types (default: all). |
allow | Free | comma list | Detect everything but leave these types visible. |
min_confidence | Free | 0–1 | Detection threshold (default 0.4). Lower = higher recall (catches more, over-redacts more); higher = fewer false positives (but more misses). For sensitive data, prefer a lower value — an extra black box is safer than a leaked identifier — and review with the confidence scores. |
language | Free | en · fr · de · es · it | OCR + name/location language (default en). |
region | Free | country code · eu · na | Restricts detection to that country/region's national IDs + universal types — other countries' IDs are not searched, so look-alike patterns can't false-positive. Default: all countries. An explicit entities list overrides it. See scopes below. |
color | Free | #RRGGBB | Fill colour of solid boxes. |
style | Paid | box · blur · pixelate | Obfuscation style. box and pixelate are irreversible; blur is sized to fully destroy the text. |
padding | Paid | 0–100 | Expand each region by N pixels for safer coverage. |
show_labels | Paid | true / false | Draw the detected entity type above each region. |
400.
Region scopes
region accepts a country code, or a region that expands to several countries. Only that scope's national IDs plus the universal types are detected.
| Value | Scope |
|---|---|
na | us, ca |
eu | gb, fr, es, it, de, pl, fi, se, ch, nl, be, ie |
| country | us United States · ca Canada · gb United Kingdom · fr France · es Spain · it Italy · de Germany · pl Poland · fi Finland · se Sweden · ch Switzerland · nl Netherlands · be Belgium · ie Ireland |
Detection quality & review
Privshot detects PII with OCR plus pattern and NLP matching. It is best-effort: it will not catch 100% of PII 100% of the time, and it has no human review step when called through the API. Treat every redaction as a draft your system must validate before trusting it — a missed region is an un-redacted leak.
What every response gives you
| Field | Where | Meaning |
|---|---|---|
score | each box (/analyze) | Detection confidence, 0–1. Lower means less certain. |
regions_count | JSON body · X-Regions-Count header | How many regions were detected/redacted. |
min_confidence_found | JSON body | Lowest confidence among the returned regions (null if none). |
review_recommended | JSON body · X-Review-Recommended header | true when a region is below 0.6 confidence, or when nothing was detected — either may warrant a manual look. |
Recommended workflow for sensitive data
- Call
/analyzefirst and inspect each boxscore. - Gate on
review_recommended— route those images to a human or re-run with a lowermin_confidence. - Bias toward over-redaction: a lower threshold blacks out more, which is safer than missing an identifier.
- Rely on structured identifiers (IBAN, cards, SSN, national IDs) where you can — they are checksum-validated and far more reliable than free-text name/address detection.
Idempotency
Send an Idempotency-Key header (any unique string, e.g. a UUID) to make retries safe. If the same key is replayed within 24 hours, the API returns the original response — without processing or charging again — and sets Idempotent-Replayed: true.
A concurrent request reusing a key that is still processing returns 409. Reuse a key only for identical retries of the same request.
Usage headers
Every authenticated response includes your remaining allowance and rate-limit state:
| Header | Meaning |
|---|---|
X-Credits-Remaining | Credits left (paid requests). |
X-Free-Requests-Remaining | Free requests left today (free requests). |
X-RateLimit-Remaining | Requests left in the current per-minute window. |
X-Regions-Count | Regions detected/redacted (on binary redact responses). |
X-Review-Recommended | true/false — see Detection quality (on binary redact responses). |
Entity types
52 PII categories are detected automatically — contact details, financial identifiers (IBAN, cards, crypto), and government / national IDs across the EU & North America. Fetch the live list any time from GET /entities.
Detection accuracy varies by entity type and image quality. We recommend reviewing auto-detected boxes before using the output in production workflows.
Languages
OCR and name/location detection run in the language you pass via the language option (default en). Structured identifiers (IBAN, national IDs, …) are detected regardless of language. Currently available:
Names are recognised per language by the NLP model — pass the matching language for best accuracy.
Street addresses (STREET_ADDRESS) are detected across the common EN, FR, ES and DE layouts
(e.g. 1600 Amphitheatre Parkway, 12 Rue de la Paix, Calle Mayor 10, Bahnhofstraße 12).
Rate limits
| Tier | Daily quota | Per-minute limit | Watermark | Credits |
|---|---|---|---|---|
| Free | 20 requests | 60 / min | Yes | — |
| Paid | Unlimited | 60 / min | No | 1 credit / request |
When a limit is exceeded, the API returns 429 Too Many Requests. Retry after the reset window (midnight UTC for daily limits).
Credits are purchased in one-time packs from your dashboard and never expire.