# Requests and responses

Every request is multipart/form-data with the PDF in a file field, and single-output responses are application/pdf. The uniform, stateless contract behind every action.

Every action in the API shares one contract. You send a `multipart/form-data`
request with your PDF in a `file` field, and you get the processed document back
as the response body. There is no job to poll, no upload step, and no resource to
clean up afterward — one request in, one document out. Learn this shape once and
every action page reads the same way.

## Every request looks the same

Each action is a single `POST` to `/v1/<action>` with a `multipart/form-data`
body. Three things are always present:

- The `X-API-Key` header carrying your secret key, over HTTPS.
- A `file` part containing the input PDF.
- Zero or more string parts for the action's options (for example `line_1` or
  `pages`), named exactly as the action reference lists them.

Here is a complete request that stamps a watermark, shown as raw HTTP:

```http
POST /v1/add_text_watermark HTTP/1.1
Host: api.pdfblocks.com
X-API-Key: your_api_key
Content-Type: multipart/form-data; boundary=----PdfBlocksBoundary

------PdfBlocksBoundary
Content-Disposition: form-data; name="file"; filename="input.pdf"
Content-Type: application/pdf

%PDF-1.7
<binary PDF bytes>
------PdfBlocksBoundary
Content-Disposition: form-data; name="line_1"

CONFIDENTIAL
------PdfBlocksBoundary--
```

Reading it part by part:

- **Request line** — `POST /v1/add_text_watermark`. The action name is the path;
  the method is always `POST`.
- **`X-API-Key`** — your key authenticates the request. See
  [Authentication](/docs/api/authentication).
- **`Content-Type`** — `multipart/form-data` with a boundary string. Any HTTP
  client's multipart helper sets this header and the boundary for you; you rarely
  write it by hand.
- **The `file` part** — the input PDF, sent as binary.
- **Option parts** — one part per option, here `line_1`. Each is a plain string
  value.

You never assemble that body yourself. Every language's HTTP client builds it
from a file handle and a few fields. The same request in cURL:

```bash title="cURL"
curl https://api.pdfblocks.com/v1/add_text_watermark \
  -H 'X-API-Key: your_api_key' \
  -F file=@input.pdf \
  -F line_1='CONFIDENTIAL' \
  -o watermarked.pdf
```

<Info>
  The default base URL is `https://api.pdfblocks.com`. To keep processing in a
  specific jurisdiction, swap the host for a regional one — see
  [Regions and data residency](/docs/api/regions-and-data-residency). Only the
  host changes; the path, headers, and body are identical everywhere.
</Info>

## Every response is the document

A single-output action responds with `200 OK` and the processed PDF as the raw
body:

```http
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Length: 48213

%PDF-1.7
<binary PDF bytes>
```

The body is the finished document — not JSON wrapping a URL, and not a base64
string. Stream it straight to a file or pass it to the next step in your
pipeline. In cURL that is the `-o watermarked.pdf` above; in code it is writing
`response` bytes to disk, exactly as the examples on each action page do.

## Stateless by design

The API stores nothing. Your document is processed in memory, in the region you
address, and discarded as soon as the response is written. There is no document
ID to reference later and no server-side copy to delete. Because nothing
persists between calls, each request must carry its own input `file` — including
when you chain actions, where you feed one call's output straight into the next
(see [Chaining actions](/docs/api/chaining-actions)).

## Where the contract varies

Three things sit on top of this baseline, each documented on its own page:

- **More than one input.** [Merge documents](/docs/api/merge-pdf-documents) takes
  an ordered array of `file` parts, and
  [Add an image watermark](/docs/api/add-image-watermark-to-pdf) takes a second
  binary `image` part. Both are covered in
  [Working with files](/docs/api/working-with-files).
- **More than one output.** The split family returns several documents, and you
  choose the packaging — ZIP, JSON, or multipart — with the `Accept` header. See
  [Response formats](/docs/api/response-formats).
- **Failures.** Any error returns an `application/problem+json` body following
  RFC 7807, never a partial PDF. See [Errors](/docs/api/errors).
