---
title: "Import uploaded PDFs"
method: POST
path: "/library/imports"
tags: ["Library"]
---

# Import uploaded PDFs

`POST /library/imports`

## Request

- Base URL: `https://elicit.com/api/v2`
- URL: `https://elicit.com/api/v2/library/imports`
- Auth: HTTP bearer

Imports uploaded PDFs into your library. Elicit parses each file, extracts its metadata, attaches the full text, and checks for duplicates.

1. Stage each file with `POST /api/v2/files` and PUT the bytes to `upload_url`.
2. Send the `file_id`s here. The response is `202` and an import with every file `pending`. `collectionId` adds each imported paper to a collection, duplicates included.
3. Poll `links.self` until `status` is `completed`.

Each file ends as `created` (`sourceId`), `duplicate` (`duplicateOf`), or `failed` (`error`). A file id can be imported once. Files must be PDFs. A byte-identical copy of a PDF in your library is always a `duplicate`. Do not submit overlapping import requests with the same file ids; once claimed, a file cannot be used by another import or session.

### Example

```bash
curl -X POST https://elicit.com/api/v2/library/imports \
  -H "Authorization: Bearer elk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"fileIds":["5515a6d4-1b17-4f0d-8484-ccc783b912bc"],"collectionId":"b458052a-84e2-4e47-b5c4-00e11390a265"}'
```

## Request body

- object
  - `fileIds` string[], required: Ids of staged files whose bytes have been uploaded. PDFs only; each file imports once.
  - `collectionId` string, uuid: A collection you own or can edit to add the imported sources to, duplicates included.
  - `onDuplicate` 'skip' | 'create': skip (default): a PDF matching an already-saved source is reported as its duplicate and not saved. create: saves it as a new source anyway.

## Response `202`

Import accepted; every file is pending. Poll `links.self`.

- LibraryImport
  - `id` string, uuid, required
  - `status` 'processing' | 'completed', required
  - `files` object[], required
    - `fileId` string, uuid, required
    - `filename` string, required
    - `status` 'pending' | 'created' | 'duplicate' | 'failed', required
    - `sourceId` string, uuid, nullable, required
    - `duplicateOf` string, uuid, nullable, required: The already-saved source this file matched.
    - `error` object, nullable, required: processing-error and server-error may succeed on retry.
      - `code` 'duplicate' | 'processing-error' | 'server-error' | 'invalid-file' | 'unknown', required
      - `message` string, required
  - `createdAt` string, required
  - `completedAt` string, nullable, required
  - `links` object, required
    - `self` string, required: Poll this URL until status is completed.

## Other responses

- `400`: A file is not a PDF, a file has not been uploaded, or the body is invalid.
- `401`: Authentication failed. The API key is missing, invalid, revoked, or expired.
- `403`: API access is unavailable on your plan, or your role does not allow this action.
- `404`: A file_id is unknown or belongs to another user, or the collection is not visible to you.
- `409`: A file_id was already imported or attached to a session.
- `410`: The staged upload expired before it was imported; stage it again.
- `429`: Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes.
- `500`: An unexpected error occurred. Retry reads with backoff; before retrying a write, check whether it took effect. See Error Handling for retry guidance.

## Changes

- **2026-10-13** `27c80b9a3470`: 7 info
  - added the optional property `error/details` to the response with the `400` status
  - added the optional property `error/details` to the response with the `401` status
  - added the optional property `error/details` to the response with the `403` status
  - added the optional property `error/details` to the response with the `404` status
  - …3 more
- **2026-09-27** `9b5b75b828ab`: 7 info
  - added the optional property `error/sessionId` to the response with the `400` status
  - added the optional property `error/sessionId` to the response with the `401` status
  - added the optional property `error/sessionId` to the response with the `403` status
  - added the optional property `error/sessionId` to the response with the `404` status
  - …3 more
- **2026-09-11** `acdbab329322`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/elicit/apis/elicit-api/changes/library/imports/post.md)

---

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