# RedactTool: current capability contract RedactTool 1.3.0. Configure your service base URL and Bearer key. ## Supported inputs and output PDF (including scans), DOCX, XLSX, TXT, MD. 20 MiB upload cap. PDF output is rasterized, without a searchable text layer. DOCX/XLSX retain their format; complex layouts are not universally certified. Modes: blackout or placeholder (singular). Placeholders are per job. No exposed restoration mapping or cross-job identity guarantee. Automatic detection may miss information, particularly handwriting. ## REST lifecycle Authorization: Bearer API_KEY on every /v1 request. POST /v1/files: multipart file, bounded upload. Returns file_id. POST /v1/redactions: JSON file_id, mode; Idempotency-Key header (8–100 word/hyphen characters; ASCII recommended). Returns job with id, status, stage, done, total, error, mode, redactions, download_url. GET /v1/redactions/{id}: poll queued/running to completed/failed. GET /v1/redactions/{id}/file: authenticated download after completed. Reuse creation key only with the same file and mode. Persist IDs. A local timeout does not cancel remote processing. No cancellation endpoint. No webhook, no public download URL, no remote URL import. ## Authentication, limits and data Current keys are session-bound, up to 24h. New key revokes previous key. Current trial: global queue 12; per session 2 active / 20 daily jobs. No permanent API credentials or deployed billing assumed. Terminal jobs and associated files are eligible for cleanup after 24h. An independent worker checks every 60 seconds; failures are retried. Active jobs and files referenced by active/newer jobs are retained. Files are processed only on servers managed by RedactTool, using its proprietary redaction engine and dedicated processing pipeline. Production confidential uploads need verified HTTPS transport. Do not put credentials in URLs, client-side bundles or prompts. No SOC2/HIPAA/zero-retention/zero-miss claim is made. Submitted documents are not used for model training. Inference is self-hosted; document content is not sent to third-party LLM APIs. ## MCP POST /mcp: stateless Streamable HTTP JSON-RPC, Bearer header. Protocol 2025-03-26. initialize, initialized notification, ping, tools/list, tools/call. No SSE or OAuth. Client must support custom Bearer header. First upload bytes via REST. Tools: redact_file(file_id,mode,request_id), get_result(job_id). Tool response content[].text contains the JSON job. Check result.isError. Download via REST with same owner key when completed. ## Documentation - [Quickstart](quickstart.md) - [API](api.md) - [MCP](mcp.md) - [OpenAPI](../../openapi.json) - [Tool schemas](../../mcp-tools.json) - [Python example](../examples/redact.py) # Python quickstart Set REDACTTOOL_BASE_URL, REDACTTOOL_API_KEY and REDACTTOOL_FILE. Use a trusted HTTPS endpoint. Requires requests. Use your own authorized file and credentials. The official base URL is https://redacttool.app. Use HTTPS for uploads and downloads. ```python """RedactTool REST example. Supply your own endpoint and key. No network activity occurs until this script is explicitly executed. Requires: pip install requests """ import os import time import uuid from pathlib import Path from urllib.parse import urlparse import requests base = os.environ["REDACTTOOL_BASE_URL"].rstrip("/") key = os.environ["REDACTTOOL_API_KEY"] source = Path(os.environ.get("REDACTTOOL_FILE", "sample.txt")) parsed = urlparse(base) if parsed.scheme != "https" and parsed.hostname not in {"localhost", "127.0.0.1"} and os.environ.get("REDACTTOOL_ALLOW_HTTP_TRIAL") != "1": raise ValueError("Use HTTPS, or explicitly set REDACTTOOL_ALLOW_HTTP_TRIAL=1 for non-confidential trial files") output = source.with_name(source.stem + "-redacted" + source.suffix) if output.exists(): raise FileExistsError(output) session = requests.Session() session.headers["Authorization"] = "Bearer " + key def checked(response): response.raise_for_status() return response.json() with source.open("rb") as content: uploaded = checked(session.post(base + "/v1/files", files={"file": (source.name, content)}, timeout=(15, 120))) # Keep this ID if you retry this same creation request. request_id = uuid.uuid4().hex job = checked(session.post(base + "/v1/redactions", headers={"Idempotency-Key": request_id}, json={"file_id": uploaded["file_id"], "mode": "placeholder"}, timeout=(15, 60))) print("Job:", job["id"]) # A local wait timeout does not cancel server processing. deadline = time.monotonic() + 3600 while job["status"] not in {"completed", "failed"}: if time.monotonic() >= deadline: raise TimeoutError("Resume polling this job ID; do not create a new job") time.sleep(5) job = checked(session.get(base + "/v1/redactions/" + job["id"], timeout=(15, 60))) if job["status"] == "failed": raise RuntimeError(job.get("error") or "job_failed") # Use a known same-origin path, never an arbitrary returned host. with session.get(base + "/v1/redactions/" + job["id"] + "/file", stream=True, timeout=(15, 120)) as result: result.raise_for_status() with output.open("xb") as saved: for chunk in result.iter_content(65536): saved.write(chunk) print("Saved:", output) ``` # REST API ## REST lifecycle Authorization: Bearer API_KEY on every /v1 request. POST /v1/files: multipart file, bounded upload. Returns file_id. POST /v1/redactions: JSON file_id, mode; Idempotency-Key header (8–100 word/hyphen characters; ASCII recommended). Returns job with id, status, stage, done, total, error, mode, redactions, download_url. GET /v1/redactions/{id}: poll queued/running to completed/failed. GET /v1/redactions/{id}/file: authenticated download after completed. Reuse creation key only with the same file and mode. Persist IDs. A local timeout does not cancel remote processing. No cancellation endpoint. No webhook, no public download URL, no remote URL import. ## Authentication, limits and data Current keys are session-bound, up to 24h. New key revokes previous key. Current trial: global queue 12; per session 2 active / 20 daily jobs. No permanent API credentials or deployed billing assumed. Terminal jobs and associated files are eligible for cleanup after 24h. An independent worker checks every 60 seconds; failures are retried. Active jobs and files referenced by active/newer jobs are retained. Files are processed only on servers managed by RedactTool, using its proprietary redaction engine and dedicated processing pipeline. Production confidential uploads need verified HTTPS transport. Do not put credentials in URLs, client-side bundles or prompts. No SOC2/HIPAA/zero-retention/zero-miss claim is made. Submitted documents are not used for model training. Inference is self-hosted; document content is not sent to third-party LLM APIs. Errors: 401 authentication; 404 inaccessible/missing/expired object; 409 idempotency conflict or result not ready; 413/415/422 input validation; 429 capacity or trial limit. HTTP error body uses detail; failed jobs use error. # MCP ## MCP POST /mcp: stateless Streamable HTTP JSON-RPC, Bearer header. Protocol 2025-03-26. initialize, initialized notification, ping, tools/list, tools/call. No SSE or OAuth. Client must support custom Bearer header. First upload bytes via REST. Tools: redact_file(file_id,mode,request_id), get_result(job_id). Tool response content[].text contains the JSON job. Check result.isError. Download via REST with same owner key when completed. Example tools/call: ```json { "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "redact_file", "arguments": { "file_id": "YOUR_UPLOADED_FILE_ID", "mode": "placeholder", "request_id": "unique-request-001" } } } ``` # Integration checklist The live playground uses same-origin browser-session authentication. Server integrations use Bearer keys, never embedded in public JavaScript. Trial keys expire within24h; there is no long-lived production key or billing yet. Persist file_id, job_id and a random Idempotency-Key before waiting. Retry GET with bounded backoff. For an unknown creation outcome, replay the SAME file_id/mode and key; never generate a new key blindly. 401: obtain credentials through the owning session. 404: check ownership/expiry. 409: check idempotency binding or unfinished result. 429: back off and respect current limits. Failed jobs expose error; no result file exists. Current MCP is JSON-RPC over POST /mcp; it does not offer SSE, OAuth discovery or stdio. Upload bytes through REST first; redact_file accepts a file_id, not a local path or remote URL. Check both JSON-RPC error and result.isError. Read returned content[].text as JSON, poll get_result, then download with the same Bearer key. Runnable client: /assets/examples/mcp_redact.py. Use /examples.html for actual original/output pairs and /evaluation.html for dated English test coverage. Sample documents are fictional. These fixtures demonstrate behavior, not universal accuracy.