---
title: "List documents"
method: GET
path: "/documents"
tags: ["Documents"]
---

# List documents

`GET /documents`

## Request

- Base URL: `https://inkseal.net/api/v1`
- URL: `https://inkseal.net/api/v1/documents`
- Auth: HTTP bearer

The workspace's document inventory, newest first. Every upload appears, including one that has no envelope yet, so a document an agent left behind stays rediscoverable. Each row carries the envelope built from the document when one exists, plus the signer and signed counts for that envelope. Only public ids are returned: storage keys and internal row ids are never exposed. Ordering is `createdAt` descending with the internal id breaking ties, so a row cannot appear on two pages of one walk or be skipped between them.

## Query parameters

- `page` integer
- `limit` integer
- `search` string
- `status` 'all' | 'none' | 'draft' | 'sending' | 'pending' | 'completing' | 'completed' | 'declined' | 'voided' | 'expired'
- `source` 'all' | 'web' | 'email' | 'api'
- `archived` 'active' | 'only' | 'all'

## Response `200`

A page of documents.

- object
  - `data` DocumentSummary[], required
    - `id` string, required: A document's public id: a 21-character URL-safe nanoid. Internal row ids and storage keys are never exposed.
    - `status` 'processing' | 'ready' | 'failed', required: Where the document is in conversion. `processing` from the moment the record is created until the background job finishes; then `ready` or `failed`.
    - `originalFilename` string, required
    - `originalMimeType` 'application/pdf' | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' | 'application/msword' | 'application/rtf' | 'text/rtf' | 'application/vnd.oasis.opendocument.text' | 'application/vnd.openxmlformats-officedocument.presentationml.presentation' | 'text/plain' | 'text/markdown' | 'text/html' | 'image/png' | 'image/jpeg' | 'image/webp', required: The content type declared at creation. This is checked against the uploaded file's leading bytes at confirmation when the format has a reliable signature, so it has to be the truth. `text/html` accepts `.html` and `.htm` files up to 10 MB during conversion. The file must be self-contained and is rejected without alteration at the first forbidden construct: - Any `<script>` element, including inside SVG; any `on*` event attribute; or a `javascript:` or `vbscript:` URL. - Any `<iframe>`, `<frame>`, `<frameset>`, `<object>`, `<embed>`, `<applet>`, `<base>`, `<form>`, `<link>`, `<meta http-equiv>`, `<video>`, `<audio>`, `<track>`, or `<portal>` construct. - Any `src`, `href`, `srcset`, `poster`, `background`, `xlink:href`, `data`, `formaction`, or `ping` value unless it is empty, a bare fragment, or an allowed image data URL. Relative and scheme-relative references are external. - Any CSS `@import` or `@font-face`, any `url()` outside the allowed data-image rule, or any `image-set()` with an external member, in either `<style>` or a `style` attribute. - Any data URL except `image/png`, `image/jpeg`, `image/webp`, or `image/gif`; SVG images, fonts, media, and all other data types are rejected. Chromium independently disables JavaScript, runs offline, and aborts non-data and non-about requests. The normalized PDF follows the same 200-page limit and downstream workflow as every other source format.
    - `originalSizeBytes` integer, required: The uploaded file's size in bytes. Corrected to the object's real size at confirmation.
    - `pageCount` integer, nullable, required: Null until conversion has finished.
    - `processingError` string, nullable, required: Why conversion failed, when it did.
    - `envelope` DocumentEnvelopeSummary, required: The envelope built from this document, when one exists.
      - `id` string, required: The envelope's public id.
      - `status` 'draft' | 'sending' | 'pending' | 'completing' | 'completed' | 'declined' | 'voided' | 'expired', required
      - `createdVia` 'web' | 'email' | 'api' | 'null', nullable, required: How the envelope was created.
      - `archivedAt` string, date-time, nullable, required: When the envelope was archived, or null when it is active.
    - `signerCount` integer, required: Recipients on the envelope, whatever their role. Zero when there is no envelope.
    - `signedCount` integer, required: How many of those recipients have signed. Approvals and acknowledgements are not signatures; see completedCount.
    - `completedCount` integer, required: How many of those recipients have finished their step: signed, approved or acknowledged.
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
  - `pagination` Pagination, required: Where the returned page sits in the full result set.
    - `page` integer, required: The 1-based page returned.
    - `limit` integer, required: Items per page, as requested.
    - `total` integer, required: Total items matching the query.
    - `totalPages` integer, required: `ceil(total / limit)`.

## Other responses

- `400`: The request is malformed or the resource is in the wrong state for a synchronous check. Codes: `validation_error`, `invalid_body`, `invalid_parameter`, `invalid_idempotency_key`, `invalid_event_id`, `invalid_file`, `invalid_url`, `invalid_status`, `key_mismatch`, `no_signers`, `not_completed`, `envelope_exists`, `document_not_ready`, `upload_failed`.
- `401`: The credential is missing, malformed, unknown, expired, revoked, or past its rotation grace window. Code: `unauthorized`. Every authentication failure is deliberately indistinguishable.
- `403`: The credential is valid but may not do this. Codes: `insufficient_scope` (the route's scopes are not all held; `details` names `requiredScopes` and `missingScopes`), `forbidden` (the capability check on the resolved resource failed), `scope_escalation` (a grant wider than the caller's own was requested).
- `429`: A limit was reached. Codes: `rate_limited` (the credential's per-bucket HTTP limit, or the per-workspace detection throttle), `workspace_limit_exceeded` (a workspace content or send limit; `details.limit` names it), `daily_budget_exceeded` (the workspace's daily detection budget). The four rate-limit headers are sent on this response and on no successful one, so a client cannot read its remaining budget without being refused. Retrying after `Retry-After` is always safe: a rate-limit refusal happens before the handler runs.
- `503`: A dependency the request needs is unreachable and nothing was changed. Codes: `queue_unavailable` (a background job could not be enqueued; retry the call), `billing_unavailable` (Stripe would not open a checkout session; nothing was charged, retry the call), `service_unavailable` (the rate-limit store is down, so the request was refused before running).

---

[API](https://skmtc.dev/inkseal/apis/inkseal-api.md) · [All operations](https://skmtc.dev/inkseal/apis/inkseal-api/llms.txt) · [OpenAPI document](https://skmtc.dev/inkseal/apis/inkseal-api/revisions/c440c981d578?raw)
