Workflow blueprint / Public records

FOIA redaction workflow

A visual blueprint for public-records teams that need to redact sensitive PDF content, require human approval, and publish only the safe derivative.

Does it run today?

This separates the public workflow template from currently deployed workflow execution.

Status
Schema-only template today
Create
POST /v1/workflows with this definition returns object=workflow, execution_mode=step_definition, runnable=false, readiness.status=schema_only.
Run
POST /v1/runs against this workflow returns HTTP 409 with "Workflow definition is schema-only; step execution is not deployed yet."

This FOIA redaction workflow can be created, inspected, embedded, and visualized today. It does not execute end-to-end yet because the deployed finite step runner only supports the invoice human-review subset.

Example runs

Workflow-specific visual before/after artifacts plus sample I/O for developers evaluating whether the template matches their own queue, review, and publish path.

exrun_foia_county_email_release

County email release package

A records team prepares a release package with staff emails, phone numbers, account numbers, and addresses that must be reviewed before publish.

schema only
Before

Source FOIA package PDF

Sensitive source
Open before PDF
After

Redacted derivative PDF

Publish candidate
Open after PDF

Input

{
  "pdf_url": "https://agency.example/records/foia-request-2026-019.pdf",
  "redaction_policy": {
    "pii": [
      "ssn",
      "email",
      "phone",
      "address",
      "account_number"
    ],
    "timing": "before_publish"
  },
  "reviewer": {
    "role": "records_officer",
    "approval_key": "foia-redaction"
  },
  "publish": {
    "visibility": "signed",
    "include_audit_manifest": true,
    "include_proof_cards": true
  }
}

Output

{
  "redacted_document_id": "doc_redacted_...",
  "published_view": "https://app.okrapdf.com/view/...",
  "redaction_decision_log": [
    {
      "page": 2,
      "entity": "email",
      "decision": "approved"
    }
  ],
  "audit_manifest": {
    "source_document_id": "doc_source_...",
    "derivative_document_id": "doc_redacted_...",
    "reviewer": "records_officer"
  }
}

Lifecycle

  1. create workflow definition
  2. start run after the redaction/publish runner supports this step set
  3. intake private source PDF
  4. detect redaction candidates
  5. wait for human.approval
  6. apply true redactions
  7. sanitize metadata, forms, and annotations
  8. publish redacted derivative
POST/v1/workflows

Create or import the workflow

Request

{
  "name": "FOIA redaction workflow",
  "definition": {
    "steps": "see template snapshot"
  }
}

Response

{
  "object": "workflow",
  "workflow_id": "wf_...",
  "execution_mode": "step_definition",
  "runnable": false,
  "readiness": {
    "status": "schema_only"
  }
}
POST/v1/runs

Attempt run today

Request

{
  "workflow_id": "wf_...",
  "inputs": {
    "pdf_url": "https://agency.example/records/foia-request-2026-019.pdf"
  }
}

Response

{
  "status": 409,
  "error": "Workflow definition is schema-only; step execution is not deployed yet"
}
  • This example run is attached to the FOIA workflow template for SEO, docs, and import screens.
  • It is not a standalone sample PDF and it is not a claim that the redaction/publish runner is live.
  • The same shape becomes executable when the deployed finite runner supports the redaction, approval, sanitize, and publish step set.

Quick relevance checks

If these API patterns look familiar, this workflow template is probably relevant. The goal is the same developer ergonomics as async AI job APIs, but for PDF redaction and human review.

fal-style async queue

Relevant when redaction, OCR, sanitization, or review can take longer than a blocking API request should stay open.

Similar pattern: Submit a long-running job, keep a request id, poll status/results, or receive a webhook.

Okra pattern: Create or import a workflow, start a run with PDF inputs, wait on status_url or webhook events, then fetch the approved output.

Good fit for backend queues, agent workers, batch portals, and document automation that already treat AI work as jobs.

Replicate-style prediction

Relevant when product teams need a stable run record that can be shown to a reviewer or support person, not just a final file.

Similar pattern: Create a prediction with input, get an id plus status URL, optionally include a webhook, then inspect the web view.

Okra pattern: A workflow run has a workflow_id, run_id, status_url, approval gate, and visualization endpoint for the live run graph.

Good fit if you want prediction-like lifecycle semantics for PDF operations with human review before publish.

n8n community workflow

Relevant when the workflow itself is the artifact: sales pages, docs, internal enablement, and customer-specific variants.

Similar pattern: Public template page for discovery, isolated visual embed for sharing, JSON definition for import or automation.

Okra pattern: workflows.okrapdf.com hosts crawlable metadata and JSON; embed.okrapdf.com renders only the isolated workflow visual.

Good fit for SEO pages, integration docs, and template galleries where private runs must stay separated from public content.

API examples

These examples show the route family and response shapes a developer can recognize before deciding whether to import the template or build a custom workflow.

POST/v1/workflows

Create a dynamic workflow definition

Use the resource-style workflow API to store a configurable workflow source. This mirrors a model or function registration step.

Expected response shape
{
  "object": "workflow",
  "id": "wf_...",
  "workflow_id": "wf_...",
  "version_id": "wv_...",
  "execution_mode": "agent_workflow_script",
  "runnable": true,
  "run": null
}
const source = [
  "phase('Detect');",
  "const plan = await agent('Detect FOIA redactions in the supplied PDF.', { label: 'redactions' });",
  "phase('Review');",
  "const decision = await human.approval({ approval_key: 'foia-redaction', prompt: 'Approve redactions before publish', event_type: 'redaction-approval', timeout: '24 hours', on_timeout: 'reject' });",
  "return { plan, decision };"
].join("\n");

const workflow = await fetch("https://api.okrapdf.com/v1/workflows", {
  method: "POST",
  headers: {
    "Authorization": "Bearer $OKRAPDF_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    name: "FOIA redaction review",
    definition: { code: source }
  })
}).then((res) => res.json());
POST/v1/runs

Run it like an async job

This is the run shape for executable workflows. For this FOIA step-definition template today, the API returns 409 until the redaction/publish runner lands.

Expected response shape
{
  "object": "run",
  "id": "dynrun_...",
  "run_id": "dynrun_...",
  "workflow_id": "wf_...",
  "status": "queued",
  "status_url": "/v1/runs/dynrun_..."
}
const run = await fetch("https://api.okrapdf.com/v1/runs", {
  method: "POST",
  headers: {
    "Authorization": "Bearer $OKRAPDF_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    workflowId: workflow.id,
    inputs: {
      pdf_url: "https://example.gov/request.pdf",
      webhook_url: "https://example.com/webhooks/okra"
    }
  })
}).then((res) => res.json());
GET/v1/runs/{run_id}/visualization

Show status and the live run graph

Fetch the status endpoint for lifecycle state, and fetch the visualization endpoint when you want a UI to show the current node and review gate.

Expected response shape
{
  "object": "workflow_run_visualization_projection",
  "version": "okra.workflow.run.visualization.v1",
  "run_id": "dynrun_...",
  "nodes": [
    "intake",
    "detect",
    "review",
    "publish"
  ],
  "current_step": "review"
}
const status = await fetch(run.status_url, {
  headers: { "Authorization": "Bearer $OKRAPDF_API_KEY" }
}).then((res) => res.json());

const visual = await fetch(`https://api.okrapdf.com/v1/runs/${run.run_id}/visualization`, {
  headers: { "Authorization": "Bearer $OKRAPDF_API_KEY" }
}).then((res) => res.json());

Human review checklist

  • Every redaction has a page, bbox, entity class, and reviewer decision.
  • Rejected or unresolved detections block publish instead of silently passing through.
  • Metadata and hidden text are removed after redaction, not before review.
  • The public URL points to the redacted derivative, never the source PDF.

Workflow outputs

  • Redacted PDF derivative
  • Signed or public review link
  • Redaction decision log
  • Audit manifest with source and derivative ids

Common questions

Why put human review before publish?

FOIA and public-records releases often need a reviewer to confirm both over-redaction and under-redaction risk before the PDF leaves the private workspace.

Does this publish the original PDF?

No. The workflow keeps the original private and publishes a redacted derivative after approval and sanitization.

Can the workflow handle scanned records?

The blueprint includes OCR/page-image review so scanned PDFs can surface visual redaction candidates, not only selectable text.

Is this legal advice?

No. This page describes a technical document workflow. Agencies and counsel still decide what must be withheld or released.