# Free PDF utilities

Free document mechanics inside the Emboss artifact workflow: merge, compose, extract, delete, reorder, rotate, inspect and lock PDF artifacts without downloading or re-uploading them, and use the result directly in a fill or a fax. See the guide at /docs/pdf-utilities.

## Compose a PDF

```
POST /utilities/compose_pdf
```

Authentication: Bearer API key required.

Build one PDF from several artifacts, each with an optional page selection and rotation. Anonymous callers send an artifact_token per source instead of a Bearer key.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| sources | body | array | yes | Up to twenty entries of {artifact_id, pages, rotate}. pages is a selection like 1-3,7 (omit for every page); rotate is 90, 180 or 270. |
| artifact_token | body | string | no | Per source entry, for pay-per-call callers: the artifact_token returned next to that source's artifact_id. |
| Idempotency-Key | header | string | no | Optional, for an account caller. Retrying with the same key answers 200 with the original run instead of running again. Scoped to your account, valid 24 hours, and shared by every call on the account, so use a fresh key for each request. |

```curl
curl -X POST https://api.getemboss.ai/utilities/compose_pdf \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{"sources": [
        {"artifact_id": "<cover letter>"},
        {"artifact_id": "<filled form>", "pages": "1-2"}]}'
```

```js
const res = await fetch("https://api.getemboss.ai/utilities/compose_pdf", {
  method: "POST",
  headers: { Authorization: "Bearer sk_...", "Content-Type": "application/json" },
  body: JSON.stringify({
    sources: [{ artifact_id: "<cover letter>" }, { artifact_id: "<filled form>", pages: "1-2" }],
  }),
});
const { artifact_id } = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/utilities/compose_pdf",
    headers={"Authorization": "Bearer sk_..."},
    json={"sources": [{"artifact_id": "<cover letter>"}, {"artifact_id": "<filled form>", "pages": "1-2"}]},
)
artifact_id = res.json()["artifact_id"]
```

### Response

```json
{
  "operation_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "status": "ready",
  "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a",
  "artifacts": [
    { "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a", "role": "output", "mime_type": "application/pdf" }
  ]
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 200 | The run's result: operation_id, status, artifact_id, artifacts, and for inspect_pdf and flatten_pdf a report. |
| 400 | bad_request, invalid_page_spec, page_out_of_range, duplicate_page, missing_page, empty_output, or pdf_required: the body is malformed, a pages or order value is invalid, or a source is not a PDF with a known page count. |
| 404 | not_found: no such artifact, or owned by another key or token. |
| 410 | gone: the artifact's bytes have already been deleted. |
| 413 | too_many_pages, too_many_inputs, or file_too_large: a source or the result exceeds the page limit, more than twenty sources, or the sources together exceed the size limit. |
| 422 | pdf_encrypted, pdf_corrupt or pdf_unsafe: the PDF is encrypted, could not be read, or has form fields built in a way that could compromise the service (for pdf_unsafe the message is "Emboss does not process PDF files that could compromise the service."). For flatten_pdf also pdf_signed (This PDF is digitally signed. Locking it would change the file and break the signature.) and xfa_dynamic (This form is built with Adobe's dynamic XFA format, which only Adobe Reader can draw, so it can't be locked.). |
| 429 | rate_limited: more than one hundred and twenty runs in an hour for this scope. |

## Merge whole PDFs

```
POST /utilities/merge_pdf
```

Authentication: Bearer API key required.

Join whole PDFs in order, no page selection. Anonymous callers send an artifact_token per source instead of a Bearer key.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| sources | body | array | yes | Up to twenty entries of {artifact_id}, joined in order. For page selections use compose_pdf. |
| artifact_token | body | string | no | Per source entry, for pay-per-call callers: the artifact_token returned next to that source's artifact_id. |
| Idempotency-Key | header | string | no | Optional, for an account caller. Retrying with the same key answers 200 with the original run instead of running again. Scoped to your account, valid 24 hours, and shared by every call on the account, so use a fresh key for each request. |

```curl
curl -X POST https://api.getemboss.ai/utilities/merge_pdf \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{"sources": [{"artifact_id": "<first>"}, {"artifact_id": "<second>"}]}'
```

```js
const res = await fetch("https://api.getemboss.ai/utilities/merge_pdf", {
  method: "POST",
  headers: { Authorization: "Bearer sk_...", "Content-Type": "application/json" },
  body: JSON.stringify({ sources: [{ artifact_id: "<first>" }, { artifact_id: "<second>" }] }),
});
const { artifact_id } = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/utilities/merge_pdf",
    headers={"Authorization": "Bearer sk_..."},
    json={"sources": [{"artifact_id": "<first>"}, {"artifact_id": "<second>"}]},
)
artifact_id = res.json()["artifact_id"]
```

### Response

```json
{
  "operation_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "status": "ready",
  "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a",
  "artifacts": [
    { "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a", "role": "output", "mime_type": "application/pdf" }
  ]
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 200 | The run's result: operation_id, status, artifact_id, artifacts, and for inspect_pdf and flatten_pdf a report. |
| 400 | bad_request, invalid_page_spec, page_out_of_range, duplicate_page, missing_page, empty_output, or pdf_required: the body is malformed, a pages or order value is invalid, or a source is not a PDF with a known page count. |
| 404 | not_found: no such artifact, or owned by another key or token. |
| 410 | gone: the artifact's bytes have already been deleted. |
| 413 | too_many_pages, too_many_inputs, or file_too_large: a source or the result exceeds the page limit, more than twenty sources, or the sources together exceed the size limit. |
| 422 | pdf_encrypted, pdf_corrupt or pdf_unsafe: the PDF is encrypted, could not be read, or has form fields built in a way that could compromise the service (for pdf_unsafe the message is "Emboss does not process PDF files that could compromise the service."). For flatten_pdf also pdf_signed (This PDF is digitally signed. Locking it would change the file and break the signature.) and xfa_dynamic (This form is built with Adobe's dynamic XFA format, which only Adobe Reader can draw, so it can't be locked.). |
| 429 | rate_limited: more than one hundred and twenty runs in an hour for this scope. |

## Extract pages

```
POST /utilities/extract_pages
```

Authentication: Bearer API key required.

Keep only the named pages of one artifact. Anonymous callers send an artifact_token instead of a Bearer key.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| artifact_id | body | string | yes | The source PDF artifact. |
| pages | body | string | yes | A page selection like 1-3,7; 1-based, repeats and any order allowed. |
| artifact_token | body | string | no | For pay-per-call callers: the artifact_token returned next to artifact_id. |
| Idempotency-Key | header | string | no | Optional, for an account caller. Retrying with the same key answers 200 with the original run instead of running again. Scoped to your account, valid 24 hours, and shared by every call on the account, so use a fresh key for each request. |

```curl
curl -X POST https://api.getemboss.ai/utilities/extract_pages \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{"artifact_id": "<source>", "pages": "2,5-9"}'
```

```js
const res = await fetch("https://api.getemboss.ai/utilities/extract_pages", {
  method: "POST",
  headers: { Authorization: "Bearer sk_...", "Content-Type": "application/json" },
  body: JSON.stringify({ artifact_id: "<source>", pages: "2,5-9" }),
});
const { artifact_id } = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/utilities/extract_pages",
    headers={"Authorization": "Bearer sk_..."},
    json={"artifact_id": "<source>", "pages": "2,5-9"},
)
artifact_id = res.json()["artifact_id"]
```

### Response

```json
{
  "operation_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "status": "ready",
  "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a",
  "artifacts": [
    { "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a", "role": "output", "mime_type": "application/pdf" }
  ]
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 200 | The run's result: operation_id, status, artifact_id, artifacts, and for inspect_pdf and flatten_pdf a report. |
| 400 | bad_request, invalid_page_spec, page_out_of_range, duplicate_page, missing_page, empty_output, or pdf_required: the body is malformed, a pages or order value is invalid, or a source is not a PDF with a known page count. |
| 404 | not_found: no such artifact, or owned by another key or token. |
| 410 | gone: the artifact's bytes have already been deleted. |
| 413 | too_many_pages, too_many_inputs, or file_too_large: a source or the result exceeds the page limit, more than twenty sources, or the sources together exceed the size limit. |
| 422 | pdf_encrypted, pdf_corrupt or pdf_unsafe: the PDF is encrypted, could not be read, or has form fields built in a way that could compromise the service (for pdf_unsafe the message is "Emboss does not process PDF files that could compromise the service."). For flatten_pdf also pdf_signed (This PDF is digitally signed. Locking it would change the file and break the signature.) and xfa_dynamic (This form is built with Adobe's dynamic XFA format, which only Adobe Reader can draw, so it can't be locked.). |
| 429 | rate_limited: more than one hundred and twenty runs in an hour for this scope. |

## Delete pages

```
POST /utilities/delete_pages
```

Authentication: Bearer API key required.

Remove the named pages of one artifact; every other page stays in order. Anonymous callers send an artifact_token instead of a Bearer key.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| artifact_id | body | string | yes | The source PDF artifact. |
| pages | body | string | yes | A page selection like 1-2,17; 1-based, repeats and any order allowed. |
| artifact_token | body | string | no | For pay-per-call callers: the artifact_token returned next to artifact_id. |
| Idempotency-Key | header | string | no | Optional, for an account caller. Retrying with the same key answers 200 with the original run instead of running again. Scoped to your account, valid 24 hours, and shared by every call on the account, so use a fresh key for each request. |

```curl
curl -X POST https://api.getemboss.ai/utilities/delete_pages \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{"artifact_id": "<source>", "pages": "1-2,17"}'
```

```js
const res = await fetch("https://api.getemboss.ai/utilities/delete_pages", {
  method: "POST",
  headers: { Authorization: "Bearer sk_...", "Content-Type": "application/json" },
  body: JSON.stringify({ artifact_id: "<source>", pages: "1-2,17" }),
});
const { artifact_id } = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/utilities/delete_pages",
    headers={"Authorization": "Bearer sk_..."},
    json={"artifact_id": "<source>", "pages": "1-2,17"},
)
artifact_id = res.json()["artifact_id"]
```

### Response

```json
{
  "operation_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "status": "ready",
  "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a",
  "artifacts": [
    { "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a", "role": "output", "mime_type": "application/pdf" }
  ]
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 200 | The run's result: operation_id, status, artifact_id, artifacts, and for inspect_pdf and flatten_pdf a report. |
| 400 | bad_request, invalid_page_spec, page_out_of_range, duplicate_page, missing_page, empty_output, or pdf_required: the body is malformed, a pages or order value is invalid, or a source is not a PDF with a known page count. |
| 404 | not_found: no such artifact, or owned by another key or token. |
| 410 | gone: the artifact's bytes have already been deleted. |
| 413 | too_many_pages, too_many_inputs, or file_too_large: a source or the result exceeds the page limit, more than twenty sources, or the sources together exceed the size limit. |
| 422 | pdf_encrypted, pdf_corrupt or pdf_unsafe: the PDF is encrypted, could not be read, or has form fields built in a way that could compromise the service (for pdf_unsafe the message is "Emboss does not process PDF files that could compromise the service."). For flatten_pdf also pdf_signed (This PDF is digitally signed. Locking it would change the file and break the signature.) and xfa_dynamic (This form is built with Adobe's dynamic XFA format, which only Adobe Reader can draw, so it can't be locked.). |
| 429 | rate_limited: more than one hundred and twenty runs in an hour for this scope. |

## Reorder pages

```
POST /utilities/reorder_pages
```

Authentication: Bearer API key required.

Put one artifact's pages in a new order; every page is named exactly once. Anonymous callers send an artifact_token instead of a Bearer key.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| artifact_id | body | string | yes | The source PDF artifact. |
| order | body | array of integers | yes | Every page number, 1-based, named exactly once, in the new order. |
| artifact_token | body | string | no | For pay-per-call callers: the artifact_token returned next to artifact_id. |
| Idempotency-Key | header | string | no | Optional, for an account caller. Retrying with the same key answers 200 with the original run instead of running again. Scoped to your account, valid 24 hours, and shared by every call on the account, so use a fresh key for each request. |

```curl
curl -X POST https://api.getemboss.ai/utilities/reorder_pages \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{"artifact_id": "<source>", "order": [3, 1, 2]}'
```

```js
const res = await fetch("https://api.getemboss.ai/utilities/reorder_pages", {
  method: "POST",
  headers: { Authorization: "Bearer sk_...", "Content-Type": "application/json" },
  body: JSON.stringify({ artifact_id: "<source>", order: [3, 1, 2] }),
});
const { artifact_id } = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/utilities/reorder_pages",
    headers={"Authorization": "Bearer sk_..."},
    json={"artifact_id": "<source>", "order": [3, 1, 2]},
)
artifact_id = res.json()["artifact_id"]
```

### Response

```json
{
  "operation_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "status": "ready",
  "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a",
  "artifacts": [
    { "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a", "role": "output", "mime_type": "application/pdf" }
  ]
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 200 | The run's result: operation_id, status, artifact_id, artifacts, and for inspect_pdf and flatten_pdf a report. |
| 400 | bad_request, invalid_page_spec, page_out_of_range, duplicate_page, missing_page, empty_output, or pdf_required: the body is malformed, a pages or order value is invalid, or a source is not a PDF with a known page count. |
| 404 | not_found: no such artifact, or owned by another key or token. |
| 410 | gone: the artifact's bytes have already been deleted. |
| 413 | too_many_pages, too_many_inputs, or file_too_large: a source or the result exceeds the page limit, more than twenty sources, or the sources together exceed the size limit. |
| 422 | pdf_encrypted, pdf_corrupt or pdf_unsafe: the PDF is encrypted, could not be read, or has form fields built in a way that could compromise the service (for pdf_unsafe the message is "Emboss does not process PDF files that could compromise the service."). For flatten_pdf also pdf_signed (This PDF is digitally signed. Locking it would change the file and break the signature.) and xfa_dynamic (This form is built with Adobe's dynamic XFA format, which only Adobe Reader can draw, so it can't be locked.). |
| 429 | rate_limited: more than one hundred and twenty runs in an hour for this scope. |

## Rotate pages

```
POST /utilities/rotate_pages
```

Authentication: Bearer API key required.

Rotate named pages of one artifact by 90, 180 or 270 degrees, added clockwise to each page's current rotation. Anonymous callers send an artifact_token instead of a Bearer key.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| artifact_id | body | string | yes | The source PDF artifact. |
| rotations | body | array | yes | A non-empty list of {pages, degrees}; degrees is 90, 180 or 270. |
| artifact_token | body | string | no | For pay-per-call callers: the artifact_token returned next to artifact_id. |
| Idempotency-Key | header | string | no | Optional, for an account caller. Retrying with the same key answers 200 with the original run instead of running again. Scoped to your account, valid 24 hours, and shared by every call on the account, so use a fresh key for each request. |

```curl
curl -X POST https://api.getemboss.ai/utilities/rotate_pages \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{"artifact_id": "<source>", "rotations": [{"pages": "1", "degrees": 90}]}'
```

```js
const res = await fetch("https://api.getemboss.ai/utilities/rotate_pages", {
  method: "POST",
  headers: { Authorization: "Bearer sk_...", "Content-Type": "application/json" },
  body: JSON.stringify({ artifact_id: "<source>", rotations: [{ pages: "1", degrees: 90 }] }),
});
const { artifact_id } = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/utilities/rotate_pages",
    headers={"Authorization": "Bearer sk_..."},
    json={"artifact_id": "<source>", "rotations": [{"pages": "1", "degrees": 90}]},
)
artifact_id = res.json()["artifact_id"]
```

### Response

```json
{
  "operation_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "status": "ready",
  "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a",
  "artifacts": [
    { "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a", "role": "output", "mime_type": "application/pdf" }
  ]
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 200 | The run's result: operation_id, status, artifact_id, artifacts, and for inspect_pdf and flatten_pdf a report. |
| 400 | bad_request, invalid_page_spec, page_out_of_range, duplicate_page, missing_page, empty_output, or pdf_required: the body is malformed, a pages or order value is invalid, or a source is not a PDF with a known page count. |
| 404 | not_found: no such artifact, or owned by another key or token. |
| 410 | gone: the artifact's bytes have already been deleted. |
| 413 | too_many_pages, too_many_inputs, or file_too_large: a source or the result exceeds the page limit, more than twenty sources, or the sources together exceed the size limit. |
| 422 | pdf_encrypted, pdf_corrupt or pdf_unsafe: the PDF is encrypted, could not be read, or has form fields built in a way that could compromise the service (for pdf_unsafe the message is "Emboss does not process PDF files that could compromise the service."). For flatten_pdf also pdf_signed (This PDF is digitally signed. Locking it would change the file and break the signature.) and xfa_dynamic (This form is built with Adobe's dynamic XFA format, which only Adobe Reader can draw, so it can't be locked.). |
| 429 | rate_limited: more than one hundred and twenty runs in an hour for this scope. |

## Inspect a PDF

```
POST /utilities/inspect_pdf
```

Authentication: Bearer API key required.

Structural facts about one artifact: page count, page sizes and rotations, whether it is encrypted, has form fields, annotations, outlines, embedded files or JavaScript. No text, no field values, no new artifact is produced. Anonymous callers send an artifact_token instead of a Bearer key.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| artifact_id | body | string | yes | The PDF artifact to inspect. |
| artifact_token | body | string | no | For pay-per-call callers: the artifact_token returned next to artifact_id. |
| Idempotency-Key | header | string | no | Optional, for an account caller. Retrying with the same key answers 200 with the original run instead of running again. Scoped to your account, valid 24 hours, and shared by every call on the account, so use a fresh key for each request. |

```curl
curl -X POST https://api.getemboss.ai/utilities/inspect_pdf \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{"artifact_id": "<source>"}'
```

```js
const res = await fetch("https://api.getemboss.ai/utilities/inspect_pdf", {
  method: "POST",
  headers: { Authorization: "Bearer sk_...", "Content-Type": "application/json" },
  body: JSON.stringify({ artifact_id: "<source>" }),
});
const { report } = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/utilities/inspect_pdf",
    headers={"Authorization": "Bearer sk_..."},
    json={"artifact_id": "<source>"},
)
report = res.json()["report"]
```

### Response

```json
{
  "operation_id": "6c47f7f5-f921-4698-910f-95dd7d81310b",
  "status": "ready",
  "artifact_id": null,
  "artifacts": [],
  "report": {
    "pages": 3,
    "encrypted": false,
    "has_acroform": true,
    "has_annotations": false,
    "has_outlines": false,
    "has_embedded_files": false,
    "has_javascript": false,
    "pdf_version": "PDF-1.7",
    "page_info": [
      { "page": 1, "width_points": 612.0, "height_points": 792.0, "rotation": 0 }
    ],
    "mime_type": "application/pdf",
    "size_bytes": 184320,
    "sha256": "f2ad6f..."
  }
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 200 | The run's result: operation_id, status, artifact_id, artifacts, and for inspect_pdf and flatten_pdf a report. |
| 400 | bad_request, invalid_page_spec, page_out_of_range, duplicate_page, missing_page, empty_output, or pdf_required: the body is malformed, a pages or order value is invalid, or a source is not a PDF with a known page count. |
| 404 | not_found: no such artifact, or owned by another key or token. |
| 410 | gone: the artifact's bytes have already been deleted. |
| 413 | too_many_pages, too_many_inputs, or file_too_large: a source or the result exceeds the page limit, more than twenty sources, or the sources together exceed the size limit. |
| 422 | pdf_encrypted, pdf_corrupt or pdf_unsafe: the PDF is encrypted, could not be read, or has form fields built in a way that could compromise the service (for pdf_unsafe the message is "Emboss does not process PDF files that could compromise the service."). For flatten_pdf also pdf_signed (This PDF is digitally signed. Locking it would change the file and break the signature.) and xfa_dynamic (This form is built with Adobe's dynamic XFA format, which only Adobe Reader can draw, so it can't be locked.). |
| 429 | rate_limited: more than one hundred and twenty runs in an hour for this scope. |

## Lock a filled form

```
POST /utilities/flatten_pdf
```

Authentication: Bearer API key required.

Free. Lock a filled form: draw every field's value and every comment into the page so nothing can be edited. The new PDF has no editable fields left, keeps its links, and keeps the page count, size and rotation; the original stays as it is. A typed name is drawn in a signature box, an empty box is left blank to sign by hand, and a real digital signature is refused with 422 pdf_signed. A locked form cannot be read back or checked, so read or verify before locking. Anonymous callers send an artifact_token instead of a Bearer key.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| artifact_id | body | string | yes | The filled PDF artifact to lock. |
| artifact_token | body | string | no | For pay-per-call callers: the artifact_token returned next to artifact_id. |
| Idempotency-Key | header | string | no | Optional, for an account caller. Retrying with the same key answers 200 with the original run instead of running again. Scoped to your account, valid 24 hours, and shared by every call on the account, so use a fresh key for each request. |

```curl
curl -X POST https://api.getemboss.ai/utilities/flatten_pdf \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{"artifact_id": "<filled>"}'
```

```js
const res = await fetch("https://api.getemboss.ai/utilities/flatten_pdf", {
  method: "POST",
  headers: { Authorization: "Bearer sk_...", "Content-Type": "application/json" },
  body: JSON.stringify({ artifact_id: "<filled>" }),
});
const { artifact_id, report } = await res.json();
```

```python
import requests

res = requests.post(
    "https://api.getemboss.ai/utilities/flatten_pdf",
    headers={"Authorization": "Bearer sk_..."},
    json={"artifact_id": "<filled>"},
)
locked = res.json()["artifact_id"]
```

### Response

```json
{
  "operation_id": "0d1e5c1a-7f3b-4c52-9a43-2b6f5f0c9e11",
  "status": "ready",
  "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a",
  "artifacts": [
    { "artifact_id": "0f6b2b3e-2c7c-4c47-8c3b-9c7c7a6e5b3a", "role": "output", "mime_type": "application/pdf" }
  ],
  "report": {
    "fields_locked": 14,
    "annotations_locked": 2,
    "pages": 3,
    "calculated_left_blank": ["Total due"]
  }
}
```

### Status codes

| Code | Meaning |
| --- | --- |
| 200 | The run's result: operation_id, status, artifact_id, artifacts, and for inspect_pdf and flatten_pdf a report. |
| 400 | bad_request, invalid_page_spec, page_out_of_range, duplicate_page, missing_page, empty_output, or pdf_required: the body is malformed, a pages or order value is invalid, or a source is not a PDF with a known page count. |
| 404 | not_found: no such artifact, or owned by another key or token. |
| 410 | gone: the artifact's bytes have already been deleted. |
| 413 | too_many_pages, too_many_inputs, or file_too_large: a source or the result exceeds the page limit, more than twenty sources, or the sources together exceed the size limit. |
| 422 | pdf_encrypted, pdf_corrupt or pdf_unsafe: the PDF is encrypted, could not be read, or has form fields built in a way that could compromise the service (for pdf_unsafe the message is "Emboss does not process PDF files that could compromise the service."). For flatten_pdf also pdf_signed (This PDF is digitally signed. Locking it would change the file and break the signature.) and xfa_dynamic (This form is built with Adobe's dynamic XFA format, which only Adobe Reader can draw, so it can't be locked.). |
| 429 | rate_limited: more than one hundred and twenty runs in an hour for this scope. |

## See also

- [Free PDF utilities](https://getemboss.ai/docs/pdf-utilities)
- [Send a fax from an agent](https://getemboss.ai/use-cases/send-a-fax-from-an-agent)
