Closed Beta — Aira is currently invite-only. Request access to join the early program.
Aira

Sanitize File

Upload images, PDFs, or DICOM files for PII/PHI scanning and redaction. Supports pixel-level redaction, PS3.15 de-identification, and single-use download tokens.

The Sanitize File API handles file-level content cleaning. Upload an image, PDF, or DICOM file, choose a policy and mode, and get back a sanitized file with a full findings report.

For text sanitization, see the Sanitize API. For a conceptual overview, see the Sanitize guide.


Upload and sanitize a file

Scan and optionally redact an uploaded file.

POST /api/v1/sanitize/file
Content-Type: multipart/form-data

Requires a valid API key or JWT.

Form fields

FieldTypeRequiredDefaultDescription
filefileYesFile to scan: image, PDF, or DICOM
policystringNo"default"Policy pack: default, hipaa, pci, legal
modestringNo"redact"One of redact, tokenize, block, flag
ai_modelstringNonullModel ID for AI-assisted second-pass review
include_pixel_redactionboolNofalseEnable pixel-level redaction for DICOM burned-in text

Max file size: 50 MB

Modes

ModeBehavior
redactBlack-box PII in the file, return a single-use download token
tokenizeReplace PII with reversible tokens, return token mapping. The file is also redacted and downloadable
blockIf PII is found, block the file entirely (no download token)
flagScan only — return findings without modifying the file

Policy packs

PackLibrariesUse case
defaultpii, credentials, prompt_injectionGeneral-purpose scanning
hipaapii, credentials, prompt_injection, healthcarePHI: MRNs, diagnoses, dates, providers
pcipii, credentialsCard numbers, account data
legalpii, credentialsNames, emails, case-adjacent PII

File type detection

Files are identified by magic bytes, not the Content-Type header or extension. This prevents file-type spoofing. The extension is used only as a fallback.

TypeMagic signature
JPEG\xff\xd8\xff
PNG\x89PNG\r\n\x1a\n
GIFGIF87a / GIF89a
BMPBM
TIFFII*\0 (little-endian) / MM\0* (big-endian)
PDF%PDF
DICOMDICM at byte offset 128

Mode behavior per file type

ModeImagePDFDICOM
redactPresidio pixel-level redaction + OCR text scanPyMuPDF in-place redactionPS3.15 Annex E tag removal + optional pixel redaction
tokenizePixel redaction + token mappingIn-place redaction + token mappingPS3.15 de-identification + token mapping
blockReject if PII foundReject if PII foundReject if any finding has critical severity
flagOCR scan only, return findingsText scan only, return findingsTag text scan only, return findings

AI-assisted review

When ai_model is set, the extracted text (OCR for images, page text for PDFs, tag text for DICOM) is sent through an AI second-pass review after the rule-based scan. For images, any additional entities found by the AI model are mapped back to OCR word bounding boxes and blacked out at the pixel level.

Example

curl -X POST https://api.airaproof.com/api/v1/sanitize/file \
  -H "Authorization: Bearer $AIRA_API_KEY" \
  -F "file=@patient-record.pdf" \
  -F "policy=hipaa" \
  -F "mode=redact"

Response

{
  "file_type": "pdf",
  "original_filename": "patient-record.pdf",
  "findings": [
    {
      "entity_type": "ner_person",
      "severity": "warning",
      "action_taken": "redacted",
      "library": "pii_ner",
      "description": "NER: PERSON (score 0.92)",
      "count": 3
    },
    {
      "entity_type": "us_ssn",
      "severity": "critical",
      "action_taken": "redacted",
      "library": "pii",
      "description": "US Social Security Number",
      "count": 1
    }
  ],
  "blocked": false,
  "mode": "redact",
  "policy": "hipaa",
  "input_hash": "sha256:abc123...",
  "output_hash": "sha256:def456...",
  "download_token": "a1b2c3d4e5f6...",
  "download_url": "https://api.airaproof.com/api/v1/sanitize/file/a1b2c3d4e5f6.../download",
  "tokenized_text": "Patient [REDACTED]\nSSN: [REDACTED]\n...",
  "token_mapping": null,
  "dicom_tag_actions": null,
  "pixel_redactions": null,
  "receipt_id": "550e8400-e29b-41d4-a716-446655440000",
  "request_id": "req_xyz789"
}

Response fields

FieldTypeDescription
file_typestringDetected type: image, pdf, or dicom
original_filenamestringThe uploaded filename
findingsarrayList of detected entities (see Findings object)
blockedbooleantrue if the file was blocked (block mode only)
modestringThe mode that was applied
policystringThe policy pack that was applied
input_hashstringSHA-256 hash of the original file
output_hashstring or nullSHA-256 hash of the sanitized file. null if blocked
download_tokenstring or nullOne-time token for downloading the sanitized file. null if blocked or flag mode with no redaction
download_urlstring or nullFull URL for downloading the sanitized file
tokenized_textstring or nullThe extracted text after sanitization (redacted or tokenized)
token_mappingobject or nullToken-to-original mapping. Only present in tokenize mode
dicom_tag_actionsarray or nullDICOM tag de-identification actions. Only present for DICOM files
pixel_redactionsarray or nullPixel-level redactions applied. Only present for DICOM files with include_pixel_redaction
receipt_idstring or nullEd25519-signed receipt ID for audit trail
request_idstringUnique request identifier

Tokenize mode

When mode is "tokenize", the file is redacted (download token provided) and the response includes reversible tokens in tokenized_text and token_mapping:

{
  "file_type": "image",
  "tokenized_text": "Patient <NER_PERSON_001>, DOB <NER_DATE_TIME_001>",
  "token_mapping": {
    "<NER_PERSON_001>": "John Smith",
    "<NER_DATE_TIME_001>": "1985-03-15"
  },
  "download_token": "a1b2c3d4e5f6...",
  "download_url": "https://api.airaproof.com/api/v1/sanitize/file/a1b2c3d4e5f6.../download"
}

Use the token mapping with the Detokenize endpoint to reverse the text substitution.


DICOM response

DICOM files include additional metadata about the PS3.15 Annex E de-identification process.

dicom_tag_actions

Each entry describes an action taken on a DICOM metadata tag:

FieldTypeDescription
tag_namestringHuman-readable tag name (e.g., PatientName)
tag_numberstringDICOM tag number (e.g., (0010,0010))
actionstringAction taken: removed
original_hashstringSHA-256 hash of the original tag value (for audit, not reversal)

pixel_redactions

When include_pixel_redaction is true, burned-in text detected in the pixel data is blacked out:

FieldTypeDescription
text_foundstringThe text detected in the image
bounding_boxarrayPixel coordinates [x, y, width, height]
confidencenumberOCR confidence score (0.0 to 1.0)

Example (DICOM redact with pixel redaction)

curl -X POST https://api.airaproof.com/api/v1/sanitize/file \
  -H "Authorization: Bearer $AIRA_API_KEY" \
  -F "file=@brain-scan.dcm" \
  -F "policy=hipaa" \
  -F "mode=redact" \
  -F "include_pixel_redaction=true"
{
  "file_type": "dicom",
  "original_filename": "brain-scan.dcm",
  "findings": [
    {
      "entity_type": "ner_person",
      "severity": "warning",
      "action_taken": "redacted",
      "library": "pii_ner",
      "description": "NER: PERSON (score 0.95)",
      "count": 1
    },
    {
      "entity_type": "patient_id",
      "severity": "critical",
      "action_taken": "redacted",
      "library": "healthcare",
      "description": "DICOM PatientID tag",
      "count": 1
    }
  ],
  "blocked": false,
  "mode": "redact",
  "policy": "hipaa",
  "input_hash": "sha256:abc123...",
  "output_hash": "sha256:def456...",
  "download_token": "f7e8d9c0...",
  "download_url": "https://api.airaproof.com/api/v1/sanitize/file/f7e8d9c0.../download",
  "tokenized_text": "Patient [REDACTED], ID [REDACTED]",
  "token_mapping": null,
  "dicom_tag_actions": [
    {
      "tag_name": "PatientName",
      "tag_number": "(0010,0010)",
      "action": "removed",
      "original_hash": "sha256:a1b2..."
    },
    {
      "tag_name": "PatientID",
      "tag_number": "(0010,0020)",
      "action": "removed",
      "original_hash": "sha256:c3d4..."
    },
    {
      "tag_name": "PatientBirthDate",
      "tag_number": "(0010,0030)",
      "action": "removed",
      "original_hash": "sha256:e5f6..."
    }
  ],
  "pixel_redactions": [
    {
      "text_found": "John Smith",
      "bounding_box": [100, 50, 250, 80],
      "confidence": 0.91
    }
  ],
  "receipt_id": "550e8400-e29b-41d4-a716-446655440000",
  "request_id": "req_dicom_001"
}

Download sanitized file

Download the cleaned file using the one-time token from the sanitize response.

GET /api/v1/sanitize/file/{token}/download

No authentication required. The download token itself is the authorization.

  • Tokens expire after 1 hour
  • Tokens are single-use -- the file is deleted after the first download
  • The response filename is sanitized_<original_name>.<ext>
  • The Content-Type header matches the original file type

Path parameters

ParameterTypeRequiredDescription
tokenstringYesThe download_token from the sanitize response

Response headers

HeaderValue
Content-TypeMatches the original file type (e.g., application/pdf, image/png, application/dicom)
Content-Dispositionattachment; filename="sanitized_<original_name>.<ext>"
X-Token-Single-Usetrue

Example

curl -o sanitized-record.pdf \
  "https://api.airaproof.com/api/v1/sanitize/file/a1b2c3d4e5f6.../download"

Findings object

Every sanitize response includes a findings array:

FieldTypeDescription
entity_typestringWhat was detected (e.g., us_ssn, ner_person, mrn_pattern)
severitystringcritical, warning, or info
action_takenstringredacted, tokenized, blocked, flagged
librarystringWhich scanner found it (pii, credentials, pii_ner, healthcare)
descriptionstringHuman-readable description
countintegerHow many instances of this entity type were found

Severity behavior

SeverityRedact/TokenizeBlockFlag
criticalReplacedBlockedFlagged
warningReplacedBlockedFlagged
infoNot replaced (flagged only)BlockedFlagged

Info-severity entities (IP addresses, URLs, organization names) are reported in findings but never redacted or tokenized. This prevents false positives from being blacked out.


Error responses

StatusDescription
401Missing or invalid authentication
413File exceeds 50 MB limit
415Unsupported file type (not image, PDF, or DICOM)
422Empty file, corrupt file, or missing server dependency (e.g., PyMuPDF for PDF, pydicom for DICOM)

On this page