---
title: "Edit a PDF"
method: POST
path: "/v1/edit"
tags: ["edit"]
---

# Edit a PDF

`POST /v1/edit`

## Request

- Base URL: `https://api.niubai.vip` (the document declares no server; this is the origin it was published from)
- URL: `https://api.niubai.vip/v1/edit`
- Auth: HTTP bearer

Apply one or more edits (replace, delete, redact, insert, form fill) to a document and get the edited PDF back with every change verified. Send the document as a multipart upload (`file`) with `edits` as a JSON string, or as JSON with `source.url` or a `source.file_id` from an earlier upload. Small documents answer `200` with the result at once; larger ones (over the plan's sync page limit) and any request with `options.async` true answer `202` with a `job_id` to poll at `GET /v1/jobs/{job_id}` (or set `options.webhook_url` to be called when it finishes). Add `Accept: application/pdf` to receive the edited file itself instead of JSON. Each entry in `changes` says which font was written (`font_source`, `font_used`), whether the pixel check passed (`verified`, `collateral_pixels`) and links a before/after preview; `unmatched` and `failed` list what did not happen and why.

## Headers

- `Idempotency-Key` string

## Request body

- EditRequest (unresolved $ref)

## Response `200`

The edit ran

- EditResponse: A sync edit's body: 200 for done/partial, 422 for failed. A failed edit keeps all three lists (the spec requires them for debugging) and additionally carries the ``error`` envelope.
  - `status` string, required
  - `job_id` string, required
  - `output` OutputOut: The edited document (absent on ``dry_run`` and on a failed edit).
    - `file_id` string, required
    - `url` string, nullable
    - `expires_at` string, nullable
    - `pages` integer
    - `bytes` integer
  - `changes` ChangeOut[]
    - `edit` integer, required
    - `op` string, required
    - `page` integer, required
    - `page_label` string, nullable
    - `span_ids` string[]
    - `bbox` number[]
    - `before` string
    - `after` string
    - `context` string
    - `font_source` string
    - `font_used` string
    - `fit` object, nullable
    - `is_ocr` boolean
    - `ocr_confidence` number, nullable
    - `collateral_pixels` integer
    - `verified` boolean
    - `notes` string[]
    - `preview_url` string, nullable
  - `unmatched` UnmatchedOut[]
    - `edit` integer, required
    - `reason` string, required
    - `hint` string
    - `suggestions` object[]
  - `failed` FailedOut[]
    - `edit` integer, required
    - `reason` string, required
    - `hint` string
    - `page` integer, nullable
    - `collateral_pixels` integer, nullable
  - `warnings` string[]
  - `usage` UsageOut: What the request cost (spec §5.2's ``usage``).
    - `pages_billed` integer
    - `weights` object
    - `remaining` integer
  - `error` object, nullable

## Other responses

- `202`: Accepted as a job
- `400`: error.code is one of: invalid_request
- `401`: error.code is one of: unauthorized
- `402`: error.code is one of: quota_exceeded
- `403`: error.code is one of: forbidden_watermark_off
- `409`: error.code is one of: conflict
- `413`: error.code is one of: too_large
- `422`: error.code is one of: document_encrypted, document_unsupported, signed_document, edit_failed
- `429`: error.code is one of: rate_limited
- `500`: error.code is one of: engine_error
- `502`: error.code is one of: upstream_error
- `504`: error.code is one of: engine_timeout

---

[API](https://skmtc.dev/niubai/apis/pdf-edit-api-gateway.md) · [All operations](https://skmtc.dev/niubai/apis/pdf-edit-api-gateway/llms.txt) · [OpenAPI document](https://skmtc.dev/niubai/apis/pdf-edit-api-gateway/revisions/83ed2bb54eb5?raw)
