> This page is for version v1 (default).
> For other versions, use one of these documentation indexes:
> - v1 (default): https://docs.plextera.com/v-1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.plextera.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.plextera.com/_mcp/server.

# API Reference

The Plextera Public API exposes four endpoint groups.

---

## Files

Upload and manage files. A file can be submitted to Document Insights for extraction or referenced in a workflow.

| Endpoint              | Description                                                                                      |
| --------------------- | ------------------------------------------------------------------------------------------------ |
| `POST /files`         | Upload a file. Returns the assigned `fileId`.                                                    |
| `GET /files/{fileId}` | Retrieve file metadata, including a temporary `contentUrl` for downloading the content directly. |

**Constraints:**

* Maximum file size: **50 MB**
* Supported: PDF, JPEG, PNG, TIFF, WebP, DOCX, XLSX, PPTX, plain text, CSV, HTML, archives, audio, video
* Rejected: executable and script files
* Uploaded files are staged for downstream processing. Use them as inputs for Document Insights or workflow runs rather than as long-term file storage.

---

## Document Insights

Extract structured fields from documents and monitor asynchronous processing.

| Endpoint                                                      | Description                                                        |
| ------------------------------------------------------------- | ------------------------------------------------------------------ |
| `POST /document-insights/extractions`                         | Extract structured fields from an existing file or URL.            |
| `POST /document-insights/extractions/upload`                  | Upload a file and extract it in one request.                       |
| `GET /document-insights/extractions`                          | List recent extractions. Supports status/time filters and sorting. |
| `GET /document-insights/extractions/{extractionId}`           | Get extraction state and output.                                   |
| `POST /document-insights/extractions/{extractionId}/feedback` | Submit a field correction or comment.                              |
| `DELETE /document-insights/extractions/{extractionId}`        | Delete a terminal extraction and its stored output.                |

**Document input** - use an existing `fileId`, a public HTTPS `url`, or direct multipart upload.

**Configuration and routing** - your workspace's Document Insights configuration determines which documents match and which fields appear in `output.fields`.
Review the relevant configuration in Plextera to identify the expected output schema and routing mode.
If you do not know how to access it, ask your workspace administrator or Plextera.
The v1 API does not currently list available configurations or `docType` values.

**Labels** - optional string key-value pairs.
Custom labels are returned for correlation and do not affect extraction.
`docType` is reserved for configured Document Insights routing.
Use the exact value from the relevant configuration in Plextera; if you do not know where to find it, ask your workspace administrator or Plextera.
When default routing is available, omit `docType` but keep any custom labels you need for correlation.

**Label limits:**

* Up to 50 labels per extraction
* Label keys must be 1-64 characters
* Label values must be 1-512 characters
* Keys and values must be strings and cannot be blank
* `docType` counts as one label and follows the same limits

For setup steps, examples, and `docType` guidance, see [Document Extraction](/guides/core-guides/document-extraction).

**Extraction lifecycle:**

```
QUEUED → PROCESSING → COMPLETED
                    ↘ FAILED
                    ↘ REJECTED
```

| Status       | Meaning                                                                                                                                                                            |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `QUEUED`     | Extraction accepted, not yet started.                                                                                                                                              |
| `PROCESSING` | Actively being processed.                                                                                                                                                          |
| `COMPLETED`  | Output is ready; `outputAvailable: true`.                                                                                                                                          |
| `FAILED`     | Routing, processing, or extracted-data validation could not produce a usable result. Check `error.code` for the cause.                                                             |
| `REJECTED`   | The document could not be accepted, for example because it is duplicate, broken, empty, uses an unsupported format, or uses an unsupported language. Check `error` for the reason. |

**Output** - available on `GET /document-insights/extractions/{extractionId}` once `outputAvailable` is `true`. Extractions return a typed `fields` array with confidence scores and page placement coordinates when available.

**List extractions** - use `GET /document-insights/extractions` to review recent extractions and check their status.
It supports `status`, `from`, `to`, `sortBy`, `sort`, `page`, `size`, and deep-object label filters such as `labels[docType]=YOUR_CONFIGURED_DOCUMENT_TYPE`.
Multiple label filters use AND.
Use `GET /document-insights/extractions/{extractionId}` when you need the full output.
See [Filter by labels](/guides/core-guides/document-extraction#filter-by-labels) for a shell-safe curl example.

**List sorting** - `GET /document-insights/extractions` supports `sortBy=createdAt|updatedAt|completedAt` and `sort=asc|desc`. Defaults are `createdAt` and `desc`.

**Timestamps** - all timestamps are UTC ISO 8601 strings. `createdAt` is when Plextera accepted the extraction, `updatedAt` is the last known state change, and `completedAt` is present after the extraction reaches `COMPLETED`, `FAILED`, or `REJECTED`.

**Extraction errors** - failed and rejected extractions include `error.code` and `error.message` so clients can handle terminal failures programmatically.

| Code                         | Status     | Meaning                                                                                                            |
| ---------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------ |
| `DOCUMENT_NOT_ROUTED`        | `FAILED`   | No workspace configuration matched. Verify the exact `labels.docType` value or ask whether default routing exists. |
| `DOCUMENT_REJECTED`          | `REJECTED` | The document was rejected. Read `error.message` for the concrete reason, such as duplicate content.                |
| `DOCUMENT_EXTRACTION_FAILED` | `FAILED`   | Processing failed after the document was accepted. Retry with backoff if the problem may be transient.             |

**Deletion** - `DELETE /document-insights/extractions/{extractionId}` permanently removes a terminal extraction (`COMPLETED`, `FAILED`, `REJECTED`) and returns `204`. Deleting a `QUEUED` or `PROCESSING` extraction returns `409 CONFLICT`.

**Feedback** - after reviewing an extraction result, submit corrections per field using `POST /document-insights/extractions/{extractionId}/feedback`. Include `fieldId` to target a specific field, or omit it for a general comment. `type` defaults to `ERROR`; use `INFO` for notes that should not mark the extraction as incorrect. Feedback is surfaced to the Document Insights team for extraction quality improvement.

Feedback messages are required and limited to 1024 characters.

---

## Workflows

Trigger and monitor workflow runs. Workflows are configured in Plextera Studio and can include Document Insights steps, data transformation, and custom processing logic.

| Endpoint                            | Description                                            |
| ----------------------------------- | ------------------------------------------------------ |
| `POST /workflows/{workflowId}/runs` | Trigger a new workflow run.                            |
| `GET /workflow-runs`                | List runs, optionally filtered by status or workflow.  |
| `GET /workflow-runs/{runId}`        | Get detailed run state, step outputs, and nested runs. |

**Trigger payload** - the request body is passed to the workflow as its trigger input. Any valid JSON is accepted; the expected structure depends on the workflow's trigger configuration. Omit the body entirely if the workflow requires no input.

**Multipart trigger input** - `POST /workflows/{workflowId}/runs` also accepts `multipart/form-data` for workflows configured to consume form-data, similar to a Studio webhook trigger.

| Part type                                                              | How it appears in the workflow                            |
| ---------------------------------------------------------------------- | --------------------------------------------------------- |
| Text part, for example `state=CT`                                      | `body.state` as a string                                  |
| JSON part, for example `payload` with `Content-Type: application/json` | `body.payload` as a JSON object                           |
| File part, for example `attachments`                                   | `body.attachments` as an array of File Service file nodes |

Part names are preserved. If a workflow is configured to read `body.document`, send a file part named `document`. If it reads `body.attachments`, send one or more file parts named `attachments`. The API reference shows common fields for Try It, but clients can send workflow-specific part names as needed. Workflow part names are independent from Document Insights `labels`.

**Run lifecycle:**

```
PROCESSING → COMPLETED
          ↘ FAILED
          ↘ CLOSED
```

`CLOSED` is returned for workflow runs that were closed in Plextera Studio.

**Step output** - `GET /workflow-runs/{runId}` returns step-level status and output for each step. Steps that start nested sub-workflows expose those runs in `nestedRuns`. Use `GET /workflow-runs/{runId}` with a nested run's `id` to load full nested run details.

**Duration fields:**

* `durationMs` - wall-clock time from `createdAt` to `completedAt`; omitted until the run is terminal
* `computedDurationMs` - active processing time reported by Studio, excluding wait states and parallel idle time; it may be omitted from list summaries

---

## Event Subscriptions

Configure webhook endpoints to receive push notifications when document extractions or workflow runs reach terminal states.

| Endpoint                                                | Description                                                    |
| ------------------------------------------------------- | -------------------------------------------------------------- |
| `POST /event-subscriptions`                             | Create a subscription.                                         |
| `GET /event-subscriptions`                              | List subscriptions.                                            |
| `GET /event-subscriptions/{subscriptionId}`             | Get a subscription.                                            |
| `PATCH /event-subscriptions/{subscriptionId}`           | Update name, endpoint, event types, filters, or status.        |
| `DELETE /event-subscriptions/{subscriptionId}`          | Delete a subscription.                                         |
| `GET /events`                                           | List immutable product events with delivery summary counts.    |
| `GET /events/{eventId}`                                 | Get one event and its exact webhook payload.                   |
| `GET /events/{eventId}/deliveries`                      | List deliveries of one event across subscriptions and resends. |
| `GET /events/{eventId}/deliveries/{deliveryId}`         | Inspect one delivery and its HTTP attempts.                    |
| `POST /events/{eventId}/deliveries/{deliveryId}/resend` | Create a one-attempt resend for any delivery.                  |

**Signing secret** - Plextera generates the secret.
Create returns it once with the new active subscription.
List, get, and update never return the secret, PATCH does not accept it, and the Public API has no reveal endpoint.

**Filters** - optionally restrict workflow events to a specific `workflowId`. Document Insights events are filtered by the selected event types and do not require a filter object.

**List filters and sorting** - `GET /event-subscriptions` supports `name` (case-insensitive substring of the subscription name), `status`, `eventType`, a creation-time window (`from`/`to`), and sorting via `sortBy=createdAt|updatedAt` and `sort=asc|desc` (defaults: `createdAt`, `desc`).

**Event history** - `GET /events` returns immutable product events for the event types the workspace subscribes to, including ones that produced no delivery because the matching subscription was paused or filtered them out.
Pass `subscriptionId` to show only events delivered to one subscription; summary counts are then scoped to that subscription.
Use `GET /events/{eventId}/deliveries` to inspect every automatic delivery and manual resend across subscriptions, or pass `subscriptionId` to narrow the result.

**Delivery details** - load one delivery to inspect the event payload and up to 100 recent HTTP attempts.
The response indicates whether earlier records were omitted and redacts signatures.

**Manual resend** - resend a delivery in any state while its subscription is active.
The `202` response contains a new one-attempt delivery for the same event.

**Pausing** - set `status: paused` via PATCH to suspend deliveries without deleting the subscription. Set it back to `active` to resume.

See [Event Subscriptions](/guides/core-guides/event-subscriptions) for delivery headers, signature verification, and retry behavior.

---

## Pagination

All list endpoints (`GET /document-insights/extractions`, `GET /workflow-runs`, `GET /event-subscriptions`, `GET /events`, `GET /events/{eventId}/deliveries`) use cursor-free, zero-based page parameters:

| Parameter | Type    | Default | Max   |
| --------- | ------- | ------- | ----- |
| `page`    | integer | `0`     | None  |
| `size`    | integer | `50`    | `100` |

`page` must be `0` or greater and `size` must be between `1` and `100`; out-of-range values return `400 INVALID_REQUEST`.

Every list response includes a `pageInfo` object:

```json
{
  "data": [],
  "pageInfo": {
    "page": 0,
    "size": 50,
    "totalItems": 142,
    "totalPages": 3
  }
}
```

---

## Errors

All error responses use a common envelope:

```json
{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Request validation failed.",
    "requestId": "req_01JY7MFQZ3N8VKJPX2BT6WS0QR",
    "retryable": false,
    "details": [
      {
        "field": "labels.priority",
        "issue": "Value must not be blank."
      }
    ]
  }
}
```

| Field       | Description                                                                                                 |
| ----------- | ----------------------------------------------------------------------------------------------------------- |
| `code`      | Machine-readable error code.                                                                                |
| `message`   | Human-readable description.                                                                                 |
| `requestId` | Unique identifier for this request. Include it in bug reports and support tickets.                          |
| `retryable` | `true` if the same request may succeed on retry (e.g. transient server error).                              |
| `details`   | Present on `VALIDATION_FAILED` only. Array of field-level validation errors, each with `field` and `issue`. |

### Error codes

| HTTP | Code                     | Meaning                                                                                                                                |
| ---- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `INVALID_REQUEST`        | The request is malformed or unparseable.                                                                                               |
| 401  | `UNAUTHORIZED`           | Missing or invalid API key.                                                                                                            |
| 403  | `FORBIDDEN`              | The API key does not have permission for this operation.                                                                               |
| 404  | `NOT_FOUND`              | The requested resource does not exist.                                                                                                 |
| 405  | `METHOD_NOT_ALLOWED`     | The HTTP method is not supported for this path.                                                                                        |
| 406  | `NOT_ACCEPTABLE`         | The requested response media type is not supported.                                                                                    |
| 409  | `CONFLICT`               | The operation conflicts with existing state (for example, deleting a processing extraction or exceeding the event-subscription quota). |
| 413  | `PAYLOAD_TOO_LARGE`      | File exceeds the 50 MB limit.                                                                                                          |
| 415  | `UNSUPPORTED_MEDIA_TYPE` | Unsupported `Content-Type`.                                                                                                            |
| 422  | `VALIDATION_FAILED`      | Request was parsed but failed validation. See `details` for field-level errors.                                                        |
| 429  | `RATE_LIMITED`           | Too many requests in a short window. Back off and retry after the `Retry-After` header.                                                |
| 500  | `INTERNAL_ERROR`         | Unexpected server error. `retryable: true` - safe to retry with backoff.                                                               |
| 502  | `DOWNSTREAM_ERROR`       | An upstream service returned an unexpected error.                                                                                      |

---

## Request IDs

Every response includes an `X-Request-Id` header with a unique identifier for the request. This ID is also echoed in the `requestId` field of error responses.

```
X-Request-Id: req_01JY7MFQZ3N8VKJPX2BT6WS0QR
```

When reporting issues, always include the `X-Request-Id` - it allows Plextera to locate the exact request in server logs regardless of timing.