# Apply redaction

> `POST /job/add/paperoffice_dataripper___redact_image` · Section: Document AI — Anonymization · PaperOffice AI API, release `R20261020.1917`.

`POST https://api.paperoffice.ai/latest/job/add/paperoffice_dataripper___redact_image`

## Overview

Step 2 after Detect PII preview: black out regions and build the anonymized PDF via paperoffice_dataripper___redact_image (same path as UI and MCP). Pass files/page_files + bounding_boxes + redact_boxes + partial_regions (detected_pii.partial_regions: fragments inside a line and pseudonym replacements) from the preview job. MCP shortcut: po_anonymization_redaction_apply(preview_job_id). Legacy workflow template anonymization___request is obsolete — do not use it. Optional internal template document_anonymize_finalize exists for workflow-only finalize; prefer this redact_image endpoint.

**Cost:** 20 credits (base, at Start-SLA `no_sla` / ×1; higher lanes multiply job price)

**Parameters:**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `files` | string | Yes | Page images from preview: HTTPS download URL(s) or JSON array of page image URLs (from preview original_images / page files). Multipart file uploads also accepted. |
| `page_files` | string | No | Optional JSON array [{"page": "00001", "file": "<page image URL>"}] with the explicit page order (takes precedence over files; same payload as UI and MCP). |
| `bounding_boxes` | string | Yes | OCR geometry: JSON ocr_pages / bounding boxes from preview (required for production apply). |
| `redact_boxes` | string | Yes | JSON: which boxes to black out — typically detected_pii.redact_box_ids (per-page or global). |
| `boxes_by_page` | string | No | Alias for redact_boxes as page-keyed index arrays (e.g. {"00001":[0,2,5]}). |
| `override_boxes` | array | No | Optional manual box IDs overriding auto detection. Send only when non-empty; an empty array is ignored (R20260914.1444). |
| `partial_regions` | string | No | Partial regions per page from the preview (detected_pii.partial_regions, page-keyed JSON object): fragments inside a line and, with redact_mode=pseudonymize, the replacement texts. Pass them along unchanged, otherwise fragments stay visible and no pseudonymized PDF is produced. Extra rectangles {x, y, width, height} in percent may be added per page. |
| `redact_color` | string | No | Redaction fill color (hex) (default: "#000000") |
| `output_pdf` | string | No | true = anonymized PDF; false = redacted page images (default: "true") |
| `priority` | integer | No | Queue priority (1–900). Omit = plan default. 900 = sync when capacity allows. |
| `client_wait` | boolean | No | Connection hold: true (default) = API holds this HTTP request while the job runs, up to the dynamic pipeline timeout (priority, pages, pipeline type; minimum about 20s, infrastructure cap about 295s). Returns the finished result when ready, or HTTP 202 with job_id and poll_url if the hold is exceeded. false = immediate job_id. |
| `async_only` | boolean | No | Same as client_wait=false: immediate job_id — poll GET /job/get/{job_id}. (default: false) |

**Request body:** `multipart/form-data` (or `application/x-www-form-urlencoded`) — use form fields from the parameters table; upload via `file`, `file_1`, or `files` (all accepted) or pass `files` as a JSON array of HTTPS URLs / `source_url` / `file_url`. Do **not** send `application/json` unless the endpoint is listed as JSON-only.
**Array fields (multipart):** repeat the field name with `[]` — e.g. `override_boxes[]=value1&override_boxes[]=value2`. JSON bodies with array properties are rejected on these endpoints.
## Responses

Returns JSON with `status: "success"`; key fields: `job_id` (poll `GET /job/get/{job_id}`) or inline `result` when `client_wait=true`; after poll read `result ?? job_result`. Optional `_billing` and `processing_time`. Errors: HTTP 4xx/5xx with `status: "error"`, `code`, and `message`.

## Connection hold & polling

- **Default (`client_wait` omitted or `true`):** The API holds **this HTTP connection** while the job runs, up to the **dynamic pipeline timeout** (priority, pages, pipeline type; minimum about 20s, infrastructure cap about 295s). Returns the finished result when ready.
- **Hold exceeded:** If the job is not finished in time → **HTTP 202** with `job_id`, `poll_url`, `max_wait_seconds`, and `client_wait: false`. The job **continues in the background** — poll `GET /job/get/{job_id}` every 5–10 seconds.
- **Immediate poll mode:** `client_wait=false` or `async_only=true` → `job_id` immediately (about 100ms), then poll as above.

**Response fields:** `client_wait` (boolean) — whether this response used connection hold; `max_wait_seconds` — actual hold duration attempted.

**Completed payload key:** After polling, OCR pipelines return the payload in `job_result`; workflow/IDP (`POST /job/add/workflow`) return it in `result`. Always read `result ?? job_result`. See **Job result schema**.

**Note:** Prefer `processing_lane` Start-SLA for wait-to-start / job price — see collection guide **Start-SLA (`processing_lane`) — wait-to-start**. Legacy `priority` is compat only.

## Essentials (all endpoints)

- **Base URL:** `https://api.paperoffice.ai/latest` · **Auth:** `Authorization: Bearer po_sk_…` or `po_ut_…` (server-side only); browser code uses `po_pk_…` with an allowlisted `Origin`. No Bearer at all on a product API returns HTTP 403 `TIER_RESTRICTED`.
- **Errors:** HTTP 4xx/5xx with `status: "error"`, `code` and `message`. Retry 429 (`Retry-After`) and 5xx with exponential backoff; do not retry validation errors.
- **Jobs:** `client_wait=true` (default) holds the connection. HTTP 202 means the job is still running — poll `GET /job/get/{job_id}` every 5–10 s until `job_status` is `completed`, then read `result ?? job_result`. `processing_lane` sets the Start-SLA; legacy `priority` is not part of the public contract.
- **Billing:** every billable product call costs at least 5 credits; read `_billing.job.credits_billed` on billed responses.
- **Mutations** use `POST` with action paths (e.g. `POST /documents/document-delete`), not HTTP `DELETE`.

---

All endpoints: [llms.txt](https://api.paperoffice.ai/latest/docs/llms.txt) · Everything in one file: [llms-full.txt](https://api.paperoffice.ai/latest/docs/llms-full.txt) · [OpenAPI 3.1](https://api.paperoffice.ai/latest/docs/openapi.json) · This page: https://api.paperoffice.ai/latest/docs/endpoints/po-anonymization-apply-redaction.md

*Generated 2026-10-20 from live API documentation (release `R20261020.1917`).*
