# API Reference

The Apdf API covers two jobs: **tracking** how recipients read your PDFs, and **processing** the PDFs themselves. Pick the one you need:

## PDF Tracking & Analytics API

Share PDFs through tracked links, see how each recipient reads them, and trigger automations on their activity.

## PDF Processing API

Create, merge, split, compress, OCR and secure PDFs, read and fill their forms, or extract their text and metadata.

The base URL for all API endpoints is:

**Base URL**

```bash
https://apdf.io/api
```

## Getting Started

### Authentication

The Apdf API uses API tokens to authenticate requests. You can view and manage your API tokens in your account.

The API token should be included in the request as a bearer token value. To check a token and see which account it acts as, retrieve your account.

**Authentication**

```bash
curl https://apdf.io/api \
  -H "Authorization: Bearer TOKEN"
```

### Headers

Make sure you have the following content type headers are set on every request:

**Headers**

```bash
Accept: application/json
Content-Type: application/json
```

### Pagination

All list endpoints return paginated results wrapped in a `data` array, accompanied by `meta` and `links` objects with navigation details. Use the `page` and `per_page` query parameters to control which page is returned and how many items it contains.

**RESPONSE**

```json
{
  "data": [
    ...
  ],
  "meta": {
    "total": 75,
    "per_page": 25,
    "from": 1,
    "to": 25,
    "current_page": 1,
    "last_page": 3,
    "path": "https://apdf.io/api/docs",
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "page": null,
        "active": false
      },
      {
        "url": "https://apdf.io/api/docs?page=1",
        "label": "1",
        "page": 1,
        "active": true
      },
      {
        "url": "https://apdf.io/api/docs?page=2",
        "label": "2",
        "page": 2,
        "active": false
      },
      {
        "url": "https://apdf.io/api/docs?page=3",
        "label": "3",
        "page": 3,
        "active": false
      },
      {
        "url": "https://apdf.io/api/docs?page=2",
        "label": "Next &raquo;",
        "page": 2,
        "active": false
      }
    ]
  },
  "links": {
    "first": "https://apdf.io/api/docs?page=1",
    "last": "https://apdf.io/api/docs?page=3",
    "prev": null,
    "next": "https://apdf.io/api/docs?page=2"
  }
}
```

### Limitations

To ensure smooth and reliable API operation for all users, a few usage limitations are in place:

- Each API user is limited to 10 requests per second, up to 300 requests per minute
- Generated PDF files are stored for 60 min. before being automatically deleted
- Uploaded PDF files must not exceed 100 MB in size

### Retrieve your account

`GET /api/me`

Get the user and workspace of the API token

#### Request

```bash
curl -X GET https://apdf.io/api/me \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "user": {
      "email": "jane@acme.com",
      "name": ""
    },
    "workspace": {
      "id": "762d0-ef7db-87d6d",
      "handle": "acme",
      "name": null,
      "plan": {
        "name": "Pro",
        "tracked_documents": 100,
        "trial_ends_at": null
      }
    }
  }
}
```

## Documents

### List all documents

`GET /api/docs`

Get a list of your documents

#### Parameters

| Parameter | Required | Description                                                              |
| --------- | -------- | ------------------------------------------------------------------------ |
| status    | no       | Filter by archive state. One of `active` (default), `archived`, or `all` |

#### Request

```bash
curl -X GET https://apdf.io/api/docs \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": [
    {
      "doc_id": "68052-a7bc5-62b0b",
      "viewer_url": "https://docs.apdf.io/acme/68052-a7bc5-62b0b",
      "file_url": "https://apdf-files.s3.eu-central-1.amazonaws.com/docs/202604/35c779f069e68fefec5eb.pdf",
      "name": "Doe_Company_Personalized_Offer_2026",
      "file_size": 165310,
      "file_pages": 12,
      "is_public": false,
      "created_at": "2026-04-20T20:43:28.000000Z",
      "archived_at": null
    }
  ],
  "links": {...},
  "meta": {...}
}
```

### Create a document

`POST /api/docs`

Create a new trackable document from the given PDF

#### Parameters

| Parameter | Required | Description           |
| --------- | -------- | --------------------- |
| file      | yes      | URL of the PDF file   |
| name      | yes      | Name for the document |

#### Request

```bash
curl -X POST https://apdf.io/api/docs \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d name="DOCUMENT_NAME"
```

#### Response

```json
{
  "data": {
    "doc_id": "8b25b-86755-9f9af",
    "viewer_url": "https://docs.apdf.io/acme/8b25b-86755-9f9af",
    "file_url": "https://apdf-files.s3.eu-central-1.amazonaws.com/docs/202604/83a3cf4c69e7864ca4c44.pdf",
    "name": "Proposal_2026_04_AcmeCompany",
    "file_size": 1247378,
    "file_pages": 9,
    "is_public": false,
    "created_at": "2026-04-21T14:14:37.000000Z",
    "archived_at": null
  }
}
```

### Retrieve a document

`GET /api/docs/{doc_id}`

Get a single document by its ID

#### Request

```bash
curl -X GET https://apdf.io/api/docs/68052-a7bc5-62b0b \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "doc_id": "68052-a7bc5-62b0b",
    "viewer_url": "https://docs.apdf.io/acme/68052-a7bc5-62b0b",
    "file_url": "https://apdf-files.s3.eu-central-1.amazonaws.com/docs/202604/35c779f069e68fefec5eb.pdf",
    "name": "Doe_Company_Personalized_Offer_2026",
    "file_size": 165310,
    "file_pages": 12,
    "is_public": false,
    "created_at": "2026-04-20T20:43:28.000000Z",
    "archived_at": null
  }
}
```

### Archive a document

`POST /api/docs/{doc_id}/archive`

Archive a document

#### Request

```bash
curl -X POST https://apdf.io/api/docs/68052-a7bc5-62b0b/archive \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "doc_id": "68052-a7bc5-62b0b",
    "viewer_url": "https://docs.apdf.io/acme/68052-a7bc5-62b0b",
    "file_url": "https://apdf-files.s3.eu-central-1.amazonaws.com/docs/202604/35c779f069e68fefec5eb.pdf",
    "name": "Doe_Company_Personalized_Offer_2026",
    "file_size": 165310,
    "file_pages": 12,
    "is_public": false,
    "created_at": "2026-04-20T20:43:28.000000Z",
    "archived_at": "2026-05-21T09:14:02.000000Z"
  }
}
```

### Unarchive a document

`POST /api/docs/{doc_id}/unarchive`

Restore a previously archived document

#### Request

```bash
curl -X POST https://apdf.io/api/docs/68052-a7bc5-62b0b/unarchive \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "doc_id": "68052-a7bc5-62b0b",
    "viewer_url": "https://docs.apdf.io/acme/68052-a7bc5-62b0b",
    "file_url": "https://apdf-files.s3.eu-central-1.amazonaws.com/docs/202604/35c779f069e68fefec5eb.pdf",
    "name": "Doe_Company_Personalized_Offer_2026",
    "file_size": 165310,
    "file_pages": 12,
    "is_public": false,
    "created_at": "2026-04-20T20:43:28.000000Z",
    "archived_at": null
  }
}
```

### Make a document public

`POST /api/docs/{doc_id}/public`

Make a document viewable without a recipient link

#### Request

```bash
curl -X POST https://apdf.io/api/docs/68052-a7bc5-62b0b/public \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "doc_id": "68052-a7bc5-62b0b",
    "viewer_url": "https://docs.apdf.io/acme/68052-a7bc5-62b0b",
    "file_url": "https://apdf-files.s3.eu-central-1.amazonaws.com/docs/202604/35c779f069e68fefec5eb.pdf",
    "name": "Doe_Company_Personalized_Offer_2026",
    "file_size": 165310,
    "file_pages": 12,
    "is_public": true,
    "created_at": "2026-04-20T20:43:28.000000Z",
    "archived_at": null
  }
}
```

### Make a document private

`POST /api/docs/{doc_id}/private`

Make a document viewable only through a recipient link

#### Request

```bash
curl -X POST https://apdf.io/api/docs/68052-a7bc5-62b0b/private \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "doc_id": "68052-a7bc5-62b0b",
    "viewer_url": "https://docs.apdf.io/acme/68052-a7bc5-62b0b",
    "file_url": "https://apdf-files.s3.eu-central-1.amazonaws.com/docs/202604/35c779f069e68fefec5eb.pdf",
    "name": "Doe_Company_Personalized_Offer_2026",
    "file_size": 165310,
    "file_pages": 12,
    "is_public": false,
    "created_at": "2026-04-20T20:43:28.000000Z",
    "archived_at": null
  }
}
```

### Delete a document

`DELETE /api/docs/{doc_id}`

Delete a document and its underlying PDF file

#### Request

```bash
curl -X DELETE https://apdf.io/api/docs/68052-a7bc5-62b0b \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
[]
```

## Recipient Links

### List all recipient links

`GET /api/docs/{doc_id}/links`

Get a list of all recipient links for a document

#### Request

```bash
curl -X GET https://apdf.io/api/docs/68052-a7bc5-62b0b/links \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": [
    {
      "token": "fi6WgjyH",
      "name": "John Doe",
      "email": "john.doe@example.com",
      "url": "https://docs.apdf.io/acme/68052-a7bc5-62b0b?v=fi6WgjyH",
      "is_active": true,
      "last_viewed_at": "2026-04-21T09:12:44.000000Z",
      "created_at": "2026-04-20T20:43:28.000000Z"
    }
  ],
  "links": {...},
  "meta": {...}
}
```

### Create a recipient link

`POST /api/docs/{doc_id}/links`

Create a new recipient link for a document

#### Parameters

| Parameter | Required | Description            |
| --------- | -------- | ---------------------- |
| name      | yes      | Name of the recipient  |
| email     | no       | Email of the recipient |

#### Request

```bash
curl -X POST https://apdf.io/api/docs/68052-a7bc5-62b0b/links \
  -H "Authorization: Bearer TOKEN" \
  -d name="RECIPIENT_NAME" \
  -d email="RECIPIENT_EMAIL"
```

#### Response

```json
{
  "data": {
    "token": "fi6WgjyH",
    "name": "John Doe",
    "email": "john.doe@example.com",
    "url": "https://docs.apdf.io/acme/68052-a7bc5-62b0b?v=fi6WgjyH",
    "is_active": true,
    "last_viewed_at": null,
    "created_at": "2026-04-21T14:14:37.000000Z"
  }
}
```

### Delete a recipient link

`DELETE /api/docs/{doc_id}/links/{token}`

Delete a recipient link of a document

#### Request

```bash
curl -X DELETE https://apdf.io/api/docs/68052-a7bc5-62b0b/links/fi6WgjyH \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
[]
```

### Activate a recipient link

`POST /api/docs/{doc_id}/links/{token}/activate`

Activate (enable) a recipient link of a document

#### Request

```bash
curl -X POST https://apdf.io/api/docs/68052-a7bc5-62b0b/links/fi6WgjyH/activate \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "token": "fi6WgjyH",
    "name": "John Doe",
    "email": "john.doe@example.com",
    "url": "https://docs.apdf.io/acme/68052-a7bc5-62b0b?v=fi6WgjyH",
    "is_active": true,
    "last_viewed_at": null,
    "created_at": "2026-04-21T14:14:37.000000Z"
  }
}
```

### Deactivate a recipient link

`POST /api/docs/{doc_id}/links/{token}/deactivate`

Deactivate (disable) a recipient link of a document

#### Request

```bash
curl -X POST https://apdf.io/api/docs/68052-a7bc5-62b0b/links/fi6WgjyH/deactivate \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "token": "fi6WgjyH",
    "name": "John Doe",
    "email": "john.doe@example.com",
    "url": "https://docs.apdf.io/acme/68052-a7bc5-62b0b?v=fi6WgjyH",
    "is_active": false,
    "last_viewed_at": null,
    "created_at": "2026-04-21T14:14:37.000000Z"
  }
}
```

## Analytics

### Sessions with KPIs

`GET /api/docs/{doc_id}/analytics`

Get aggregate KPIs across all sessions of a document

#### Request

```bash
curl -X GET https://apdf.io/api/docs/68052-a7bc5-62b0b/analytics \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "sessions": 4,
    "unique_viewers": 3,
    "avg_duration_ms": 207469,
    "completion_rate": 100,
    "pages_per_session": 5,
    "prints": 2,
    "downloads": 3,
    "form_submissions": 1,
    "annotations": 14
  }
}
```

### List all sessions

`GET /api/docs/{doc_id}/analytics/sessions`

Get a paginated list of viewer sessions

#### Request

```bash
curl -X GET https://apdf.io/api/docs/68052-a7bc5-62b0b/analytics/sessions \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": [
    {
      "session_id": "0lLKvtyoC1nl3WD0",
      "viewer_id": "OLHe7I5rXTBz",
      "recipient": {
        "name": "John Doe",
        "email": "john.doe@example.com"
      },
      "device_type": "desktop",
      "browser": "Firefox",
      "os": "Ubuntu",
      "referer": null,
      "utm_source": null,
      "created_at": "2026-04-21 20:23:07.394",
      "pages_viewed": 6,
      "total_duration_ms": 83926,
      "completion_pct": 85,
      "prints": 1,
      "downloads": 0
    }
  ],
  "links": {...},
  "meta": {...}
}
```

### Retrieve a session

`GET /api/docs/{doc_id}/analytics/sessions/{session_id}`

Get the full detail of a single viewer session

#### Request

```bash
curl -X GET https://apdf.io/api/docs/68052-a7bc5-62b0b/analytics/sessions/0lLKvtyoC1nl3WD0 \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "session": {
      "session_id": "0lLKvtyoC1nl3WD0",
      "viewer_id": "OLHe7I5rXTBz",
      "recipient": {
        "name": "John Doe",
        "email": "john.doe@example.com"
      },
      ...
    },
    "metrics": {
      "total_duration_ms": 89364,
      "pages_viewed": 3,
      "total_pages": 3,
      "completion_pct": 100,
      "downloads": 0,
      "prints": 1
    },
    "pages": [
      {
        "page": 1,
        "views": 3,
        "duration_ms": 85730,
        "viewed": true
      },
      {
        "page": 2,
        "views": 2,
        "duration_ms": 797,
        "viewed": true
      },
      {
        "page": 3,
        "views": 1,
        "duration_ms": 2837,
        "viewed": true
      }
    ],
    "events": [
      {
        "event": "document:loaded",
        "page": null,
        "duration_ms": null,
        "total_pages": 3,
        "payload": {
          "numPages": 3
        },
        "created_at": "2026-04-21 20:56:24.177"
      },
      {
        "event": "page:enter",
        "page": 1,
        "duration_ms": null,
        "total_pages": 3,
        "payload": {
          "page": 1,
          "total": 3
        },
        "created_at": "2026-04-21 20:56:24.702"
      },
      {
        "event": "annotation:update",
        "page": 1,
        "duration_ms": null,
        "total_pages": null,
        "payload": {
          "annotation_id": "annot_1776805002364_5uxvr3fcx",
          "type": "highlight",
          "comment": "Thanks for the offer, let's talk",
          "author": "John Doe"
        },
        "created_at": "2026-04-21 20:57:12.118"
      },
      {
        "event": "document:print",
        "page": null,
        "duration_ms": null,
        "total_pages": null,
        "payload": null,
        "created_at": "2026-04-21 20:57:44.220"
      },
      {
        "event": "page:leave",
        "page": 3,
        "duration_ms": 2837,
        "total_pages": null,
        "payload": {
          "page": 3,
          "duration": 2837
        },
        "created_at": "2026-04-21 20:57:52.581"
      }
    ]
  }
}
```

## Collaboration

### List all annotations

`GET /api/docs/{doc_id}/annotations`

Get all annotations on a document

#### Request

```bash
curl -X GET https://apdf.io/api/docs/68052-a7bc5-62b0b/annotations \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": [
    {
      "annotation_id": "annot_1776805044335_stzuj7fyu",
      "page": 1,
      "type": "underline",
      "creator_id": "OLHe7I5rXTBz",
      "recipient": {
        "name": "John Doe",
        "email": "john.doe@example.com"
      },
      "annotated_text": "Proposed timeline: 3 months",
      "comment_author": "John Doe",
      "comment_text": "This needs adjustments",
      "replies": [],
      "created_at": "2026-04-21T20:57:24.000000Z"
    },
    {
      "annotation_id": "annot_1776805002364_5uxvr3fcx",
      "page": 1,
      "type": "highlight",
      "creator_id": "OLHe7I5rXTBz",
      "recipient": {
        "name": "John Doe",
        "email": "john.doe@example.com"
      },
      "annotated_text": "Your personalized Offer",
      "comment_author": "John Doe",
      "comment_text": "Thanks for the offer, let's talk",
      "replies": [
        {
          "author": "Jane Smith",
          "text": "Happy to! How about Thursday at 10:00?",
          "created_at": "2026-04-22T09:14:03.000000Z"
        }
      ],
      "created_at": "2026-04-21T20:56:42.000000Z"
    }
  ],
  "links": {...},
  "meta": {...}
}
```

### Add a comment

`POST /api/docs/{doc_id}/annotations/{annotation_id}/comments`

Add a comment to an annotation: the opening comment if it has none yet, otherwise a reply. Comments added through the API don't trigger automations.

#### Parameters

| Parameter | Required | Description                      |
| --------- | -------- | -------------------------------- |
| author    | yes      | Name shown as the comment author |
| text      | yes      | The comment text                 |

#### Request

```bash
curl -X POST https://apdf.io/api/docs/68052-a7bc5-62b0b/annotations/annot_1776805002364_5uxvr3fcx/comments \
  -H "Authorization: Bearer TOKEN" \
  -d author="AUTHOR_NAME" \
  -d text="COMMENT_TEXT"
```

#### Response

```json
{
  "data": {
    "annotation_id": "annot_1776805002364_5uxvr3fcx",
    "page": 1,
    "type": "highlight",
    "creator_id": "OLHe7I5rXTBz",
    "recipient": {
      "name": "John Doe",
      "email": "john.doe@example.com"
    },
    "annotated_text": "Your personalized Offer",
    "comment_author": "John Doe",
    "comment_text": "Thanks for the offer, let's talk",
    "replies": [
      {
        "author": "Jane Smith",
        "text": "Happy to! How about Thursday at 10:00?",
        "created_at": "2026-04-22T09:14:03.000000Z"
      }
    ],
    "created_at": "2026-04-21T20:56:42.000000Z"
  }
}
```

### List all form submissions

`GET /api/docs/{doc_id}/form-submissions`

Get all form submissions of a document

#### Request

```bash
curl -X GET https://apdf.io/api/docs/68052-a7bc5-62b0b/form-submissions \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": [
    {
      "doc_id": "b75f9-6c031-a24c6",
      "creator_id": "OLHe7I5rXTBz",
      "recipient": {
        "name": "John Doe",
        "email": "john.doe@example.com"
      },
      "fields": [
        {
          "id": "126R",
          "name": "name",
          "page": 1,
          "type": "text",
          "value": "John Doe"
        },
        {
          "id": "127R",
          "name": "email",
          "page": 1,
          "type": "text",
          "value": "john.doe@example.com"
        },
        {
          "id": "128R",
          "name": "gender",
          "page": 1,
          "type": "radio",
          "value": true,
          "checked": true,
          "exportValue": "Male"
        },
        {
          "id": "131R",
          "name": "confirmation",
          "page": 2,
          "type": "checkbox",
          "value": true,
          "checked": true,
          "exportValue": "Confirm"
        }
      ],
      "created_at": "2026-04-21T21:12:45.000000Z",
      "updated_at": "2026-04-21T21:12:45.000000Z"
    }
  ],
  "links": {...},
  "meta": {...}
}
```

## Automations

### List all automations

`GET /api/automations`

Get a list of your automations

#### Request

```bash
curl -X GET https://apdf.io/api/automations \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": [
    {
      "id": "d4a0d-ab87b-88b6b",
      "name": "Ping CRM on document open",
      "is_active": true,
      "scope": "all",
      "doc_ids": [],
      "trigger": {
        "events": [
          "document:loaded"
        ],
        "conditions": []
      },
      "actions": [
        {
          "type": "webhook",
          "config": {
            "url": "https://crm.acme.com/webhook/document-opened",
            "headers": []
          }
        }
      ],
      "created_at": "2026-04-22T15:08:51.000000Z"
    }
  ],
  "links": {...},
  "meta": {...}
}
```

### Create an automation

`POST /api/automations`

Create a when/filter/then rule that posts reader events to your endpoint

#### Parameters

| Parameter           | Required | Description                                                                                                                                                                                                                                                                                                                                                                      |
| ------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name                | yes      | Name of the automation                                                                                                                                                                                                                                                                                                                                                           |
| scope               | no       | Which documents to watch. One of `all` (default) or `specific`                                                                                                                                                                                                                                                                                                                   |
| doc_ids             | no       | Array of document IDs to watch. Required when `scope` is `specific`, ignored otherwise                                                                                                                                                                                                                                                                                           |
| events              | yes      | Array of reader events that trigger the automation, matched with OR. Pass `*` as the only entry for every event. Valid values: document:loaded, document:download, document:print, page:enter, page:read, page:leave, text:copied, link:clicked, form:submit, annotation:create, annotation:update, annotation:delete, signature:signed, signature:declined, signature:completed |
| conditions          | no       | Array of filters that must all pass for the webhook to fire. Not available for `*`                                                                                                                                                                                                                                                                                               |
| conditions[][type]  | yes      | Valid values: `page_number`, `time_on_page` (seconds), `total_reading_time` (seconds), `pages_viewed`, `completion_rate` (percent). Only accepted when one of the given events supplies it                                                                                                                                                                                       |
| conditions[][value] | yes      | Minimum the condition compares against, in the unit of its type                                                                                                                                                                                                                                                                                                                  |
| webhook_url         | yes      | URL that receives the POST request when the automation fires                                                                                                                                                                                                                                                                                                                     |
| webhook_headers     | no       | Object of additional headers for the webhook request, e.g. `webhook_headers[Authorization]`                                                                                                                                                                                                                                                                                      |

#### Request

```bash
curl -X POST https://apdf.io/api/automations \
  -H "Authorization: Bearer TOKEN" \
  -d name="Notify sales on pricing read" \
  -d scope="specific" \
  -d doc_ids[0]="48927-c7621-ec3c0" \
  -d events[0]="page:read" \
  -d conditions[0][type]="page_number" \
  -d conditions[0][value]="7" \
  -d conditions[1][type]="time_on_page" \
  -d conditions[1][value]="30" \
  -d webhook_url="https://crm.acme.com/webhook/pricing-read" \
  -d webhook_headers[Authorization]="Bearer YOUR_SECRET"
```

#### Response

```json
{
  "data": {
    "id": "d4a0d-ab87b-88b6b",
    "name": "Notify sales on pricing read",
    "is_active": true,
    "scope": "specific",
    "doc_ids": [
      "48927-c7621-ec3c0"
    ],
    "trigger": {
      "events": [
        "page:read"
      ],
      "conditions": [
        {
          "source": "event",
          "operator": "==",
          "value": 7,
          "field": "page"
        },
        {
          "source": "event",
          "operator": ">=",
          "value": 30000,
          "field": "duration_ms"
        }
      ]
    },
    "actions": [
      {
        "type": "webhook",
        "config": {
          "url": "https://crm.acme.com/webhook/pricing-read",
          "headers": {
            "Authorization": "Bearer YOUR_SECRET"
          }
        }
      }
    ],
    "created_at": "2026-04-22T15:08:51.000000Z"
  }
}
```

### Retrieve an automation

`GET /api/automations/{automation_id}`

Get a single automation by its ID

#### Request

```bash
curl -X GET https://apdf.io/api/automations/d4a0d-ab87b-88b6b \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "id": "d4a0d-ab87b-88b6b",
    "name": "Notify sales on pricing read",
    "is_active": true,
    "scope": "specific",
    "doc_ids": [
      "48927-c7621-ec3c0"
    ],
    "trigger": {
      "events": [
        "page:read"
      ],
      "conditions": [
        {
          "field": "page",
          "value": 7,
          "source": "event",
          "operator": "=="
        },
        {
          "field": "duration_ms",
          "value": 30000,
          "source": "event",
          "operator": ">="
        }
      ]
    },
    "actions": [
      {
        "type": "webhook",
        "config": {
          "url": "https://crm.acme.com/webhook/pricing-read",
          "headers": {
            "Authorization": "Bearer YOUR_SECRET"
          }
        }
      }
    ],
    "created_at": "2026-04-22T15:08:51.000000Z"
  }
}
```

### Activate an automation

`POST /api/automations/{automation_id}/activate`

Activate (enable) an automation so it fires again

#### Request

```bash
curl -X POST https://apdf.io/api/automations/d4a0d-ab87b-88b6b/activate \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "id": "d4a0d-ab87b-88b6b",
    "name": "Notify sales on pricing read",
    "is_active": true,
    "scope": "specific",
    "doc_ids": [
      "48927-c7621-ec3c0"
    ],
    "trigger": {
      "events": [
        "page:read"
      ],
      "conditions": [
        {
          "field": "page",
          "value": 7,
          "source": "event",
          "operator": "=="
        },
        {
          "field": "duration_ms",
          "value": 30000,
          "source": "event",
          "operator": ">="
        }
      ]
    },
    "actions": [
      {
        "type": "webhook",
        "config": {
          "url": "https://crm.acme.com/webhook/pricing-read",
          "headers": {
            "Authorization": "Bearer YOUR_SECRET"
          }
        }
      }
    ],
    "created_at": "2026-04-22T15:08:51.000000Z"
  }
}
```

### Deactivate an automation

`POST /api/automations/{automation_id}/deactivate`

Deactivate (pause) an automation so it stops firing

#### Request

```bash
curl -X POST https://apdf.io/api/automations/d4a0d-ab87b-88b6b/deactivate \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "id": "d4a0d-ab87b-88b6b",
    "name": "Notify sales on pricing read",
    "is_active": false,
    "scope": "specific",
    "doc_ids": [
      "48927-c7621-ec3c0"
    ],
    "trigger": {
      "events": [
        "page:read"
      ],
      "conditions": [
        {
          "field": "page",
          "value": 7,
          "source": "event",
          "operator": "=="
        },
        {
          "field": "duration_ms",
          "value": 30000,
          "source": "event",
          "operator": ">="
        }
      ]
    },
    "actions": [
      {
        "type": "webhook",
        "config": {
          "url": "https://crm.acme.com/webhook/pricing-read",
          "headers": {
            "Authorization": "Bearer YOUR_SECRET"
          }
        }
      }
    ],
    "created_at": "2026-04-22T15:08:51.000000Z"
  }
}
```

### Duplicate an automation

`POST /api/automations/{automation_id}/duplicate`

Copy an automation, including its trigger, conditions and documents

#### Request

```bash
curl -X POST https://apdf.io/api/automations/d4a0d-ab87b-88b6b/duplicate \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": {
    "id": "9b1c7-4fe02-6a83d",
    "name": "Notify sales on pricing read (Copy)",
    "is_active": true,
    "scope": "specific",
    "doc_ids": [
      "48927-c7621-ec3c0"
    ],
    "trigger": {
      "events": [
        "page:read"
      ],
      "conditions": [
        {
          "field": "page",
          "value": 7,
          "source": "event",
          "operator": "=="
        },
        {
          "field": "duration_ms",
          "value": 30000,
          "source": "event",
          "operator": ">="
        }
      ]
    },
    "actions": [
      {
        "type": "webhook",
        "config": {
          "url": "https://crm.acme.com/webhook/pricing-read",
          "headers": {
            "Authorization": "Bearer YOUR_SECRET"
          }
        }
      }
    ],
    "created_at": "2026-04-22T15:08:51.000000Z"
  }
}
```

### Delete an automation

`DELETE /api/automations/{automation_id}`

Delete an automation and its execution history

#### Request

```bash
curl -X DELETE https://apdf.io/api/automations/d4a0d-ab87b-88b6b \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
[]
```

### List all executions

`GET /api/automations/executions`

Get a list of your automation executions

#### Request

```bash
curl -X GET https://apdf.io/api/automations/executions \
  -H "Authorization: Bearer TOKEN" \
```

#### Response

```json
{
  "data": [
    {
      "automation": {
        "id": "d4a0d-ab87b-88b6b",
        "name": "Ping CRM on document open"
      },
      "status": "successful",
      "matched_event": "document:loaded",
      "doc_id": "48927-c7621-ec3c0",
      "session_id": "ZvZiSTCWcKcnYhgp",
      "viewer_id": "0oKpyCgVWJtx",
      "payload": {
        "event": {
          "data": null,
          "recipient": {
            "name": "John Doe",
            "email": "john.doe@example.com"
          },
          "viewer_id": "0oKpyCgVWJtx",
          "session_id": "ZvZiSTCWcKcnYhgp"
        },
        "session": {
          "pages_viewed": 0,
          "completion_rate": 0,
          "total_duration_ms": 0
        },
        "trigger": {
          "matched_event": "document:loaded",
          "conditions_evaluated": false
        },
        "document": {
          "name": "Proposal_2026_04_AcmeCompany",
          "doc_id": "48927-c7621-ec3c0",
          "file_pages": 9,
          "viewer_url": "https://docs.apdf.io/acme/48927-c7621-ec3c0"
        },
        "timestamp": "2026-04-22T15:28:13+00:00",
        "automation": {
          "id": "d4a0d-ab87b-88b6b",
          "name": "Ping CRM on document open"
        }
      },
      "response": {
        "body": "{\"ok\":true}",
        "status": 200
      },
      "error": null,
      "duration_ms": 247,
      "created_at": "2026-04-22T15:28:14.000000Z"
    }
  ],
  "links": {...},
  "meta": {...}
}
```

## File

### Create PDF

`POST /api/pdf/file/create`

Create a PDF from HTML

> Async-only endpoint
>
> This endpoint always runs in the background. The response returns a `job_id` instead of the result.
>
> Poll Check Job Status or pass a `webhook_url` to receive the result when the job completes.

#### Parameters

| Parameter     | Required | Description                                                                                                                                                             |
| ------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| html          | yes      | HTML to be converted to a PDF document                                                                                                                                  |
| scale         | no       | Scale factor of the document. Valid values: 0.1 - 2                                                                                                                     |
| format        | no       | Format of the document. Valid values: letter, legal, tabloid, ledger, a0, a1, a2, a3, a4, a5, a6. Defaults to letter when neither format nor width and height are given |
| unit          | no       | Unit of the document. Valid values: px, in, cm, mm                                                                                                                      |
| width         | no       | Width of the document in mm or in the given unit                                                                                                                        |
| height        | no       | Height of the document in mm or in the given unit                                                                                                                       |
| orientation   | no       | Orientation of the document. Valid values: portrait, landscape                                                                                                          |
| margin_top    | no       | Top margin of the document in mm or in the given unit                                                                                                                   |
| margin_right  | no       | Right margin of the document in mm or in the given unit                                                                                                                 |
| margin_bottom | no       | Bottom margin of the document in mm or in the given unit                                                                                                                |
| margin_left   | no       | Left margin of the document in mm or in the given unit                                                                                                                  |
| header        | no       | Header HTML to be used for the header on all pages                                                                                                                      |
| footer        | no       | Footer HTML to be used for the footer on all pages                                                                                                                      |
| webhook_url   | no       | Result of the async job will be sent as a POST request to this URL                                                                                                      |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/file/create \
  -H "Authorization: Bearer TOKEN" \
  -d html="<html><body><h1>Hello World!</h1></body></html>"
```

#### Initial Response

```json
{
  "job_id": "01KQ2YJKAXYTHGHEXZEQ03R0XJ"
}
```

#### Job Result

```json
{
  "id": "01KQ2YJKAXYTHGHEXZEQ03R0XJ",
  "created": "2024-12-02T21:30:52.133821Z",
  "status": "successful",
  "result": {
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/6f1674e2703953aa.pdf",
    "expiration": "2024-12-02T22:30:54.450552Z",
    "pages": 1,
    "size": 11838
  }
}
```

### Split PDF

`POST /api/pdf/file/split`

Split a PDF into multiple PDF files

#### Parameters

| Parameter   | Required | Description                                                                                                                                                                                                                           |
| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                                                                                                                                   |
| pages       | yes      | Pages at which the PDF will be split, examples:<br>1,2-3,4-z = 3 PDFs with page 1, page 2 and 3, and page 4 to the end<br>n3 = every 3 pages a new PDF file<br>1-r2,z = 2 PDFs with page 1 to the penultimate page, and the last page |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint                                                                                                      |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                                                                                                                                    |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/file/split \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d pages="1-3,4,5-z"
```

#### Response

```json
[
  {
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/191674e262f952ca-1-3.pdf",
    "expiration": "2024-12-02T22:27:11.610806Z",
    "pages": 3,
    "size": 390102
  },
  {
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/191674e262f952ca-4.pdf",
    "expiration": "2024-12-02T22:27:11.610806Z",
    "pages": 1,
    "size": 241161
  },
  {
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/191674e262f952ca-5-z.pdf",
    "expiration": "2024-12-02T22:27:11.610806Z",
    "pages": 6,
    "size": 570713
  }
]
```

### Merge PDF

`POST /api/pdf/file/merge`

Merge multiple PDF files into one file

#### Parameters

| Parameter       | Required | Description                                                                                                                                                                                          |
| --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| files[]         | yes      | Array of the PDF files to merge and their options                                                                                                                                                    |
| files[i][file]  | yes      | URL of the PDF file                                                                                                                                                                                  |
| files[i][pages] | no       | Pages to be used for merging, examples:<br>1,6,4 = pages 1, 6, and 4 in that order<br>3-7 = pages 3 through 7 in increasing order<br>2,6-z = page 2 and 6 to the end<br>r3-r1 = the last three pages |
| async           | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint                                                                     |
| webhook_url     | no       | Result of the async job will be sent as a POST request to this URL                                                                                                                                   |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/file/merge \
  -H "Authorization: Bearer TOKEN" \
  -d files[0][file]="FILE_1_URL" \
  -d files[0][pages]="1,5-z" \
  -d files[1][file]="FILE_2_URL"
```

#### Response

```json
{
  "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/a736755a3dab32b8.pdf",
  "expiration": "2024-12-08T14:49:16.997135Z",
  "pages": 12,
  "size": 165310
}
```

### Compress PDF

`POST /api/pdf/file/compress`

Compress a PDF file

> Async-only endpoint
>
> This endpoint always runs in the background. The response returns a `job_id` instead of the result.
>
> Poll Check Job Status or pass a `webhook_url` to receive the result when the job completes.

#### Parameters

| Parameter   | Required | Description                                                        |
| ----------- | -------- | ------------------------------------------------------------------ |
| file        | yes      | URL of the PDF file                                                |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/file/compress \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL"
```

#### Initial Response

```json
{
  "job_id": "01KQ3A2B5CDEF6GHJK7MN8PQRS"
}
```

#### Job Result

```json
{
  "id": "01KQ3A2B5CDEF6GHJK7MN8PQRS",
  "created": "2024-12-02T21:30:52.133821Z",
  "status": "successful",
  "result": {
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/b72674993b1ae785.pdf",
    "expiration": "2024-11-30T11:13:09.716337Z",
    "size_original": 26214400,
    "size_compressed": 3145728
  }
}
```

### PDF to Image

`POST /api/pdf/file/to-image`

Convert a PDF file to images

> Async-only endpoint
>
> This endpoint always runs in the background. The response returns a `job_id` instead of the result.
>
> Poll Check Job Status or pass a `webhook_url` to receive the result when the job completes.

#### Parameters

| Parameter   | Required | Description                                                                                                                                                       |
| ----------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                                                               |
| image_type  | yes      | Image type to be generated. Valid values: png, jpeg, jpegcmyk, tiff                                                                                               |
| color_mode  | no       | Color mode of the image. Valid values: color, gray, mono                                                                                                          |
| dpi         | no       | DPI of the image. Must be between 1 and 300                                                                                                                       |
| pages       | no       | Pages to be converted (by default only the first page), examples:<br>1,4,6 = pages 1, 4, and 6<br>2,6-z = page 2 and 6 to the end<br>r3-r1 = the last three pages |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                                                                |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/file/to-image \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d image_type="jpeg"
```

#### Initial Response

```json
{
  "job_id": "01KQ3B7D9EFGH2JKLM3NP4QRTV"
}
```

#### Job Result

```json
{
  "id": "01KQ3B7D9EFGH2JKLM3NP4QRTV",
  "created": "2024-12-02T21:30:52.133821Z",
  "status": "successful",
  "result": [
    {
      "page": 1,
      "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/b72674993b1ae785-1.jpg",
      "expiration": "2024-11-30T11:13:09.716337Z"
    }
  ]
}
```

### Office to PDF

`POST /api/pdf/file/convert`

Convert an Office document (Word, Excel, PowerPoint, OpenDocument or RTF) to a PDF file

> Async-only endpoint
>
> This endpoint always runs in the background. The response returns a `job_id` instead of the result.
>
> Poll Check Job Status or pass a `webhook_url` to receive the result when the job completes.

#### Parameters

| Parameter   | Required | Description                                                                                 |
| ----------- | -------- | ------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the document. Supported formats: docx, doc, xlsx, xls, pptx, ppt, odt, ods, odp, rtf |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                          |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/file/convert \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL"
```

#### Initial Response

```json
{
  "job_id": "01KQ7F2M9BXR4TNC6WD8HJ3PZQ"
}
```

#### Job Result

```json
{
  "id": "01KQ7F2M9BXR4TNC6WD8HJ3PZQ",
  "created": "2024-12-02T21:30:52.133821Z",
  "status": "successful",
  "result": {
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/9c3e51b7a40d2f68.pdf",
    "expiration": "2024-12-02T22:30:54.450552Z",
    "pages": 8,
    "size": 269371
  }
}
```

## Page

### Extract Pages

`POST /api/pdf/page/extract`

Extract page(s) into a new PDF file

#### Parameters

| Parameter   | Required | Description                                                                                                                                                                                   |
| ----------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                                                                                           |
| pages       | yes      | Pages to be extracted, examples:<br>1,6,4 = pages 1, 6, and 4 in that order<br>3-7 = pages 3 through 7 in increasing order<br>2,6-z = page 2 and 6 to the end<br>r3-r1 = the last three pages |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint                                                              |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                                                                                            |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/page/extract \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d pages="1-3,6,9-z"
```

#### Response

```json
{
  "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/6ac674c9c031e515.pdf",
  "expiration": "2024-12-01T18:25:25.137351Z",
  "pages": 8,
  "size": 2304916
}
```

### Delete Pages

`POST /api/pdf/page/delete`

Delete page(s) from a PDF file

#### Parameters

| Parameter   | Required | Description                                                                                                                      |
| ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                              |
| pages       | yes      | Pages to be deleted, examples:<br>1,4,6 = pages 1, 4, and 6<br>2,6-z = page 2 and 6 to the end<br>r3-r1 = the last three pages   |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                               |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/page/delete \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d pages="1-3,z"
```

#### Response

```json
{
  "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/6ac674c9c031e515.pdf",
  "expiration": "2024-12-01T18:25:25.137351Z",
  "pages": 8,
  "size": 2304916
}
```

### Rotate Pages

`POST /api/pdf/page/rotate`

Rotate page(s) in a PDF file

#### Parameters

| Parameter           | Required | Description                                                                                                                                                        |
| ------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| file                | yes      | URL of the PDF file                                                                                                                                                |
| rotations[]         | yes      | Array of the rotations to perform                                                                                                                                  |
| rotations[i][angle] | yes      | Angle to rotate. Valid values: + or - followed by 0, 90, 180, 270                                                                                                  |
| rotations[i][pages] | no       | Pages to be rotated (or keep empty for all pages), examples:<br>1,5 = pages 1 and 5<br>3-7,z = pages 3 through 7 and the last page<br>r3-r1 = the last three pages |
| async               | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint                                   |
| webhook_url         | no       | Result of the async job will be sent as a POST request to this URL                                                                                                 |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/page/rotate \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d rotations[0][angle]="-90" \
  -d rotations[0][pages]="1-3" \
  -d rotations[1][angle]="+180" \
  -d rotations[1][pages]="z"
```

#### Response

```json
{
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/b72674993b1ae785.pdf",
    "expiration": "2024-12-15T13:16:12.757041Z"
}
```

### Overlay Pages

`POST /api/pdf/page/overlay`

Overlay page(s) into a PDF file

#### Parameters

| Parameter   | Required | Description                                                                                                                      |
| ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                              |
| overlay     | yes      | URL of the Overlay PDF file                                                                                                      |
| from        | no       | Pages (from the overlay pdf) to be used for overlay                                                                              |
| to          | no       | Pages (from the file pdf) that should have the overlay                                                                           |
| repeat      | no       | Pages (from the overlay pdf) that will be repeated                                                                               |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                               |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/page/overlay \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d overlay="OVERLAY_FILE_URL" \
  -d from="1,3" \
  -d to="2-z" \
  -d repeat="1"
```

#### Response

```json
{
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/b72674993b1ae785.pdf",
    "expiration": "2024-12-15T13:16:12.757041Z"
}
```

### Underlay Pages

`POST /api/pdf/page/underlay`

Underlay page(s) into a PDF file

#### Parameters

| Parameter   | Required | Description                                                                                                                      |
| ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                              |
| underlay    | yes      | URL of the Underlay PDF file                                                                                                     |
| from        | no       | Pages (from the underlay pdf) to be used for underlay                                                                            |
| to          | no       | Pages (from the file pdf) that should have the underlay                                                                          |
| repeat      | no       | Pages (from the underlay pdf) that will be repeated                                                                              |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                               |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/page/underlay \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d underlay="UNDERLAY_FILE_URL" \
  -d from="3" \
  -d to="2-z" \
  -d repeat="1"
```

#### Response

```json
{
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/b72674993b1ae785.pdf",
    "expiration": "2024-12-15T13:16:12.757041Z"
}
```

## Content

### Search Content

`POST /api/pdf/content/search`

Search in the PDF file

#### Parameters

| Parameter   | Required | Description                                                                                                                      |
| ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                              |
| text        | yes      | Text to search for                                                                                                               |
| case        | no       | Set case to 1 for a case-sensitive search                                                                                        |
| regex       | no       | Set regex to 1 to interpret the search text as a regular expression                                                              |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                               |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/content/search \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d text="SEARCH_TEXT"
```

#### Response

```json
{
  "search_text": "portable document format",
  "results_total": 3,
  "results_pages": 2,
  "results": [
    {
      "page": "6",
      "matched_line": "7. \"ISO 32000-1:2008 – Document management – Portable document format – Part 1: PDF",
      "exact_word": "Portable document format"
    },
    {
      "page": "17",
      "matched_line": "37. Adobe Systems Inc. (July 1, 2008). \"Document Management – Portable Document Format –",
      "exact_word": "Portable Document Format"
    },
    {
      "page": "17",
      "matched_line": "64. \"Processing Dangerous Paths – On Security and Privacy of the Portable Document Format\"",
      "exact_word": "Portable Document Format"
    }
  ]
}
```

### Extract Content

`POST /api/pdf/content/read`

Extract the content of the PDF file

#### Parameters

| Parameter   | Required | Description                                                                                                                      |
| ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                              |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                               |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/content/read \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL"
```

#### Response

```json
{
  "pages_total": 3,
  "characters_total": 8642,
  "pages": [
    {
      "page": 1,
      "characters": 2398,
      "content": "PDF\\nPortable Document Format (PDF), standardized as\\nISO 32000 ..."
    },
    {
      "page": 2,
      "characters": 2900,
      "content": "PDF was a proprietary format controlled by Adobe until it was released ..."
    },
    {
      "page": 3,
      "characters": 3344,
      "content": "PostScript was originally designed for a drastically different use case ..."
    }
  ]
}
```

## Form

### Read Form

`POST /api/pdf/form/read`

Get the form fields of a PDF file with their values and what each field means

#### Parameters

| Parameter   | Required | Description                                                                                                                      |
| ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file. Forms that exist only as XFA (without regular form fields) are not supported                                |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                               |

#### How it works

- A field is identified by its `name`, which /pdf/form/fill takes. Its `value` is a text for text fields, `true` or `false` for a single checkbox, the selected option (or `null`) for radios, checkbox groups and choices, and a list for multi-select listboxes. `options` lists what a field accepts
- `label` is the field's description stored in the PDF, if there is one. `context` adds the printed text around the field (and around each option), read from the page layout, so take it as a hint
- Positions are in points from the top left corner of the page as displayed, `pages` gives the size of every page

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/form/read \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL"
```

#### Response

```json
{
  "fields": [
    {
      "name": "full_name",
      "type": "text",
      "label": "Full name of the applicant",
      "value": "",
      "page": 1,
      "required": true,
      "read_only": false,
      "context": {
        "description": null,
        "position": {
          "x": 160,
          "y": 112,
          "width": 240,
          "height": 18
        },
        "visible": true,
        "text": {
          "left": "Full name",
          "right": null,
          "above": null,
          "below": "As shown in your passport",
          "row": null,
          "column": null,
          "inside": null
        }
      }
    },
    {
      "name": "contact",
      "type": "radio",
      "label": "Preferred way of contact",
      "value": null,
      "page": 1,
      "required": false,
      "read_only": false,
      "options": [
        "Email",
        "Phone"
      ],
      "context": {
        "description": null,
        "position": {
          "x": 160,
          "y": 148,
          "width": 12,
          "height": 12
        },
        "visible": true,
        "text": {
          "left": "Contact me by",
          "right": "Email",
          "above": null,
          "below": null,
          "row": null,
          "column": null,
          "inside": null
        },
        "options": [
          {
            "value": "Email",
            "position": {
              "x": 160,
              "y": 148,
              "width": 12,
              "height": 12
            },
            "text": {
              "left": "Contact me by",
              "right": "Email",
              "above": null,
              "below": null,
              "row": null,
              "column": null,
              "inside": null
            }
          },
          {
            "value": "Phone",
            "position": {
              "x": 230,
              "y": 148,
              "width": 12,
              "height": 12
            },
            "text": {
              "left": null,
              "right": "Phone",
              "above": null,
              "below": null,
              "row": "Contact me by",
              "column": null,
              "inside": null
            }
          }
        ]
      }
    },
    {
      "name": "newsletter",
      "type": "checkbox",
      "label": null,
      "value": false,
      "page": 1,
      "required": false,
      "read_only": false,
      "options": [
        "Yes"
      ],
      "context": {
        "description": null,
        "position": {
          "x": 160,
          "y": 176,
          "width": 12,
          "height": 12
        },
        "visible": true,
        "text": {
          "left": null,
          "right": "Send me the newsletter",
          "above": null,
          "below": null,
          "row": null,
          "column": null,
          "inside": null
        }
      }
    }
  ],
  "pages": [
    {
      "page": 1,
      "width": 612,
      "height": 792,
      "has_text": true
    }
  ]
}
```

### Fill Form

`POST /api/pdf/form/fill`

Fill the form fields of a PDF file

#### Parameters

| Parameter       | Required | Description                                                                                                                                                                                                                                                       |
| --------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| file            | yes      | URL of the PDF file. Forms that exist only as XFA (without regular form fields) are not supported                                                                                                                                                                 |
| fields          | yes      | Array of the fields to fill, named as /pdf/form/read returns them. Fields not in the array keep their value                                                                                                                                                       |
| fields[][name]  | yes      | Name of the field                                                                                                                                                                                                                                                 |
| fields[][value] | yes      | A text for text fields (empty clears it), `true` or `false` for a single checkbox, an option for radios, checkbox groups and comboboxes (any text if editable), one or an array of options for listboxes. Read-only, button and signature fields cannot be filled |
| flatten         | no       | Set flatten to 1 to merge the filled fields into the page content, so they cannot be changed anymore                                                                                                                                                              |
| async           | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint                                                                                                                                  |
| webhook_url     | no       | Result of the async job will be sent as a POST request to this URL                                                                                                                                                                                                |

#### How it works

- Calculated fields, like totals, are updated after filling: the standard calculations of PDF forms and simple scripted arithmetic. `calculations.unsupported` lists the calculated fields with a custom script, which keep their value
- Values are shown in the field's display format, if it has a standard one (like 1.234,50 or 14.10.2026). Numbers keep the value as given, dates are stored as shown and can be given as `YYYY-MM-DD`

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/form/fill \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d fields[0][name]="full_name" \
  -d fields[0][value]="Jane Doe" \
  -d fields[1][name]="contact" \
  -d fields[1][value]="Email" \
  -d fields[2][name]="newsletter" \
  -d fields[2][value]="true"
```

#### Response

```json
{
  "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/b72674993b1ae785.pdf",
  "expiration": "2024-11-30T11:13:09.716337Z",
  "calculations": {
    "updated": [],
    "unsupported": []
  }
}
```

### Visualize Form

`POST /api/pdf/form/visualize`

Get images of the form pages with a numbered box on every field

#### Parameters

| Parameter   | Required | Description                                                                                                                                                                  |
| ----------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                                                                          |
| pages       | no       | Pages to be rendered (by default every page with a field to fill), examples:<br>1,4,6 = pages 1, 4, and 6<br>2,6-z = page 2 and 6 to the end<br>r3-r1 = the last three pages |
| dpi         | no       | Resolution of the images. Must be between 50 and 200, default 100                                                                                                            |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint                                             |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                                                                           |

#### How it works

- Each image shows the page with a numbered box on every field to fill, numbered in reading order. `fields` tells which field each number is: its `name` (and `option` for checkboxes and radios) is what /pdf/form/fill takes
- Read-only fields and buttons are not marked. Signature fields are marked, but /pdf/form/fill cannot fill them. Hidden fields, which some forms show only on demand, get a dashed box and `hidden: true`

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/form/visualize \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d pages="1"
```

#### Response

```json
{
  "pages": [
    {
      "page": 1,
      "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/b72674993b1ae785-1.png",
      "expiration": "2024-11-30T11:13:09.716337Z",
      "fields": [
        {
          "number": 1,
          "name": "full_name",
          "type": "text"
        },
        {
          "number": 2,
          "name": "contact",
          "type": "radio",
          "option": "Email"
        },
        {
          "number": 3,
          "name": "contact",
          "type": "radio",
          "option": "Phone"
        },
        {
          "number": 4,
          "name": "newsletter",
          "type": "checkbox",
          "option": "Yes"
        }
      ]
    }
  ]
}
```

## OCR

### OCR Convert

`POST /api/pdf/ocr/convert`

Convert a scanned PDF to a PDF with selectable text (through OCR)

> Async-only endpoint
>
> This endpoint always runs in the background. The response returns a `job_id` instead of the result.
>
> Poll Check Job Status or pass a `webhook_url` to receive the result when the job completes.

#### Parameters

| Parameter   | Required | Description                                                        |
| ----------- | -------- | ------------------------------------------------------------------ |
| file        | yes      | URL of the PDF file                                                |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/ocr/convert \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL"
```

#### Initial Response

```json
{
  "job_id": "01KQ3C8E1FGHJ4KMLN5PR6STVW"
}
```

#### Job Result

```json
{
  "id": "01KQ3C8E1FGHJ4KMLN5PR6STVW",
  "created": "2024-12-02T21:30:52.133821Z",
  "status": "successful",
  "result": {
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/6f1674e2703953aa.pdf",
    "expiration": "2024-12-02T22:30:54.450552Z",
    "pages": 1,
    "size": 11838
  }
}
```

### OCR Search

`POST /api/pdf/ocr/search`

Search for text inside a scanned PDF (through OCR)

> Async-only endpoint
>
> This endpoint always runs in the background. The response returns a `job_id` instead of the result.
>
> Poll Check Job Status or pass a `webhook_url` to receive the result when the job completes.

#### Parameters

| Parameter   | Required | Description                                                         |
| ----------- | -------- | ------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                 |
| text        | yes      | Text to search for                                                  |
| case        | no       | Set case to 1 for a case-sensitive search                           |
| regex       | no       | Set regex to 1 to interpret the search text as a regular expression |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL  |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/ocr/search \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d text="SEARCH_TEXT"
```

#### Initial Response

```json
{
  "job_id": "01KQ3EAG3JKMN6PQR7STV8WXYZ"
}
```

#### Job Result

```json
{
  "id": "01KQ3EAG3JKMN6PQR7STV8WXYZ",
  "created": "2024-12-02T21:30:52.133821Z",
  "status": "successful",
  "result": {
    "search_text": "portable document format",
    "results_total": 3,
    "results_pages": 2,
    "results": [
      {
        "page": "6",
        "matched_line": "7. \"ISO 32000-1:2008 – Document management – Portable document format – Part 1: PDF",
        "exact_word": "Portable document format"
      },
      {
        "page": "17",
        "matched_line": "37. Adobe Systems Inc. (July 1, 2008). \"Document Management – Portable Document Format –",
        "exact_word": "Portable Document Format"
      },
      {
        "page": "17",
        "matched_line": "64. \"Processing Dangerous Paths – On Security and Privacy of the Portable Document Format\"",
        "exact_word": "Portable Document Format"
      }
    ]
  }
}
```

### OCR Extract

`POST /api/pdf/ocr/read`

Extract the content from a scanned PDF (through OCR)

> Async-only endpoint
>
> This endpoint always runs in the background. The response returns a `job_id` instead of the result.
>
> Poll Check Job Status or pass a `webhook_url` to receive the result when the job completes.

#### Parameters

| Parameter   | Required | Description                                                        |
| ----------- | -------- | ------------------------------------------------------------------ |
| file        | yes      | URL of the PDF file                                                |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/ocr/read \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL"
```

#### Initial Response

```json
{
  "job_id": "01KQ3D9F2HJKL5MNP6QRT7UVWX"
}
```

#### Job Result

```json
{
  "id": "01KQ3D9F2HJKL5MNP6QRT7UVWX",
  "created": "2024-12-02T21:30:52.133821Z",
  "status": "successful",
  "result": {
    "pages_total": 3,
    "characters_total": 8642,
    "pages": [
      {
        "page": 1,
        "characters": 2398,
        "content": "PDF\\nPortable Document Format (PDF), standardized as\\nISO 32000 ..."
      },
      {
        "page": 2,
        "characters": 2900,
        "content": "PDF was a proprietary format controlled by Adobe until it was released ..."
      },
      {
        "page": 3,
        "characters": 3344,
        "content": "PostScript was originally designed for a drastically different use case ..."
      }
    ]
  }
}
```

## Security

### Set Password

`POST /api/pdf/security/add`

Add password protection to the PDF

#### Parameters

| Parameter      | Required | Description                                                                                                                      |
| -------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| file           | yes      | URL of the PDF file                                                                                                              |
| owner_password | yes      | The owner password used for encryption and for setting/removing restrictions                                                     |
| user_password  | no       | The user password required to open and view the PDF                                                                              |
| async          | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint |
| webhook_url    | no       | Result of the async job will be sent as a POST request to this URL                                                               |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/security/add \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d owner_password="OWNER_PASSWORD" \
  -d user_password="USER_PASSWORD"
```

#### Response

```json
{
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/b72674993b1ae785.pdf",
    "expiration": "2024-12-15T13:16:12.757041Z"
}
```

### Remove Password

`POST /api/pdf/security/remove`

Remove password protection from the PDF

#### Parameters

| Parameter   | Required | Description                                                                                                                      |
| ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                              |
| password    | no       | The owner or user password                                                                                                       |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                               |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/security/remove \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL" \
  -d password="PASSWORD"
```

#### Response

```json
{
    "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/b72674993b1ae785.pdf",
    "expiration": "2024-12-15T13:16:12.757041Z"
}
```

## Metadata

### Read Metadata

`POST /api/pdf/metadata/read`

Get metadata from a PDF file

#### Parameters

| Parameter   | Required | Description                                                                                                                      |
| ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| file        | yes      | URL of the PDF file                                                                                                              |
| async       | no       | Set async to 1 for executing this call in the background. API will return a job ID for requesting the /job/status/check endpoint |
| webhook_url | no       | Result of the async job will be sent as a POST request to this URL                                                               |

#### Request

```bash
curl -X POST https://apdf.io/api/pdf/metadata/read \
  -H "Authorization: Bearer TOKEN" \
  -d file="FILE_URL"
```

#### Response

```json
{
  "title": "Example",
  "creator": "apdf.io",
  "producer": "Apdf/API",
  "created": "Tue Jul  1 07:24:47 2024 CEST",
  "modified": "Tue Jul  1 07:24:47 2024 CEST",
  "pages": 4,
  "encrypted": false,
  "page_size": "595.92 x 841.92 pts (A4)",
  "file_size": 221441,
  "pdf_version": "1.4"
}
```

## Jobs

### Check Job Status

`POST /api/job/status/check`

Check the job status of an asynchronous API call

#### Parameters

| Parameter | Required | Description                |
| --------- | -------- | -------------------------- |
| id        | yes      | ID of the asynchronous job |

#### Request

```bash
curl -X POST https://apdf.io/api/job/status/check \
  -H "Authorization: Bearer TOKEN" \
  -d id="JOB_ID"
```

#### Response

**RUNNING**

```json
{
    "id": "01JEB5W3960DD5363GCSPNSQVX",
    "created": "2024-12-01T10:29:26.000000Z",
    "status": "running",
    "result": null
}
```

**SUCCESSFUL**

```json
{
    "id": "01JEB5W3960DD5363GCSPNSQVX",
    "created": "2024-12-02T22:30:54.450552Z",
    "status": "successful",
    "result": {
        "file": "https://apdf-files.s3.eu-central-1.amazonaws.com/6f1674e2703953aa.pdf",
        "expiration": "2024-12-02T23:33:41.450552Z",
        "pages": 1,
        "size": 11838
    }
}
```

## Resources

- HTML documentation: https://apdf.io/docs
- Plans and quotas: https://apdf.io/pricing.md
- Sign up (free, no card) and manage API tokens: https://apdf.io/register
- MCP endpoint (OAuth 2.0, Pro and above): https://apdf.io/mcp/main
- Machine-readable site overview: https://apdf.io/llms.txt
