mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-10-03 18:23:47 +10:00
Resource-oriented REST aliases cover file imports (PDF text layer, JSON Resume, Reactive Resume v4/current, LinkedIn), PDF/DOCX/Markdown/JSON exports for resumes and cover letters, editor content checks, job-term matching and a public PDF readability checker. Collection endpoints accept limit/offset with X-Total-Count headers, and PATCH routes cover partial updates. Existing routes and response shapes stay unchanged. The OpenAPI spec marks public operations with `security: []`, the REST surface gets a 40 MiB body limit, and Better Auth publishes its own OpenAPI schema. Cookie sessions are rejected for cross-origin requests. DOCX export parses HTML with node-html-parser so it runs on the server, and PDF line extraction moves to @reactive-resume/import for reuse.
252 lines
17 KiB
Plaintext
252 lines
17 KiB
Plaintext
---
|
||
title: "Using the API"
|
||
description: "Create a Reactive Resume API key, send authenticated REST requests to read and edit your resumes, and revoke keys you no longer need."
|
||
---
|
||
|
||
The Reactive Resume REST API lets your own scripts, extensions and automations read and change your documents and job applications. You authenticate with an API key that you create in Settings. This guide walks you through creating a key, making your first request and revoking the key when you're done.
|
||
|
||
## Before you start
|
||
|
||
- You need a Reactive Resume account. The examples use the hosted instance at `https://rxresu.me`. If you self-host, replace it with your own address.
|
||
- An API key acts as you. Anyone who has it can read and edit your documents, so treat it like a password.
|
||
|
||
## Create an API key
|
||
|
||
<Steps>
|
||
<Step title="Open AI & developer settings">
|
||
Select your name at the bottom of the sidebar, choose **Settings**, then open **AI & developer**. You can also press <kbd>⌘</kbd> <kbd>K</kbd> (<kbd>Ctrl</kbd> <kbd>K</kbd> on Windows and Linux) and type "API keys".
|
||
</Step>
|
||
<Step title="Start a new key">
|
||
In the **API keys** section, select **New key**.
|
||
</Step>
|
||
<Step title="Name the key and choose when it expires">
|
||
Under **What's it for?**, enter a name that reminds you where the key is used, such as "Resume sync script". Under **Expires**, choose **30 days**, **90 days** or **Never**, then select **Create key**.
|
||
|
||
<Frame caption="The New API key dialog">
|
||
<img src="/images/guides/using-the-api/new-api-key-dialog.webp" alt="New API key dialog with the name Resume sync script entered and 90 days selected under Expires" />
|
||
</Frame>
|
||
|
||
</Step>
|
||
<Step title="Copy the key">
|
||
Select **Copy**, store the key somewhere safe (a password manager or your deployment's secret store), then select **Done**.
|
||
|
||
<Frame caption="The key is shown once, right after you create it">
|
||
<img src="/images/guides/using-the-api/api-key-shown-once.webp" alt="New API key dialog showing the generated key with a Copy button and the warning Copy it now. For your security, it won't be shown again." />
|
||
</Frame>
|
||
|
||
<Warning>
|
||
Reactive Resume shows the key only once. If you lose it, revoke it and create a new one.
|
||
</Warning>
|
||
|
||
</Step>
|
||
</Steps>
|
||
|
||
Your keys are listed in the **API keys** table with the date each was created, the date it was last used and when it expires. Expired keys disappear from the list and stop working.
|
||
|
||
<Frame caption="The API keys section in AI & developer settings">
|
||
<img
|
||
src="/images/guides/using-the-api/api-keys-section.webp"
|
||
alt="API keys table listing two keys, Claude Desktop that never expires and Resume sync script that expires on 29 Dec 2026, each with a Revoke button"
|
||
/>
|
||
</Frame>
|
||
|
||
## Make your first request
|
||
|
||
The REST API lives under `/api/openapi` on your instance. Send your key in the `x-api-key` header.
|
||
|
||
```bash
|
||
curl "https://rxresu.me/api/openapi/resumes" \
|
||
-H "x-api-key: YOUR_API_KEY"
|
||
```
|
||
|
||
The response is a JSON array of your resumes, without their full content:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"id": "01a0efa5-6529-745e-950a-521ef5b8afc7",
|
||
"name": "Game Developer Resume",
|
||
"slug": "game-developer-resume",
|
||
"tags": ["games"],
|
||
"isPublic": false,
|
||
"showDownloadButtons": true,
|
||
"isLocked": false,
|
||
"createdAt": "2026-09-30T00:09:49.101Z",
|
||
"updatedAt": "2026-09-30T00:09:49.101Z"
|
||
}
|
||
]
|
||
```
|
||
|
||
Fetch one resume with its full data, using an ID from the list:
|
||
|
||
```bash
|
||
curl "https://rxresu.me/api/openapi/resumes/01a0efa5-6529-745e-950a-521ef5b8afc7" \
|
||
-H "x-api-key: YOUR_API_KEY"
|
||
```
|
||
|
||
For request bodies, send JSON with `Content-Type: application/json`. For example, create a resume filled with sample content:
|
||
|
||
```bash
|
||
curl -X POST "https://rxresu.me/api/openapi/resumes" \
|
||
-H "x-api-key: YOUR_API_KEY" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{ "name": "Product Designer Resume", "tags": ["design"], "withSampleData": true }'
|
||
```
|
||
|
||
The response is the new resume's ID as a JSON string.
|
||
|
||
<Tip>
|
||
To change a few fields in a resume without sending the whole document, use [JSON Patch](/guides/using-the-patch-api).
|
||
</Tip>
|
||
|
||
## Find the endpoint you need
|
||
|
||
Every endpoint, with its parameters, request body and responses, is listed in the **API Reference** tab of these docs. Your own instance also serves the machine-readable OpenAPI document at `/api/openapi/spec.json` (for example `https://rxresu.me/api/openapi/spec.json`). Use the spec from the version you run when you generate a client.
|
||
|
||
| Area | Paths | What you can do |
|
||
| ------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||
| Resumes | `/resumes`, `/resumes/{id}` | List, read, create, import, update, patch, lock, duplicate, move to Trash, set a sharing password, download a PDF, read version history and statistics |
|
||
| Cover letters | `/cover-letters` | List, read, create, update, duplicate, export and import letters, restore versions, refresh their design from a resume |
|
||
| Documents | `/documents` | Work across resumes and letters: rename, tag, lock, link to an application, move to Trash, restore, delete now |
|
||
| Applications | `/applications` | Track job applications: stages, notes, interviews, attached PDFs, bulk changes, import, statistics |
|
||
| AI | `/ai-providers`, `/ai`, `/agent` | Manage your AI providers, run AI tools such as resume import from PDF, work with assistant conversations |
|
||
| Account | `/auth/account/export`, `/auth/account` | Export your account data, delete your account |
|
||
|
||
Additional app workflows have REST endpoints:
|
||
|
||
| Workflow | Endpoint |
|
||
| --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
||
| PDF, JSON Resume, Reactive Resume v4/current, LinkedIn imports | `POST /resumes/file-imports` |
|
||
| PDF, Word, Markdown and JSON exports | `GET /resumes/{id}/exports/{format}`, `GET /cover-letters/{id}/exports/{format}` |
|
||
| Editor content checks and job-term matching | `GET /resumes/{id}/checks`, `POST /resumes/{id}/job-matches` |
|
||
| Public PDF readability checker | `POST /pdf-checks` |
|
||
| File uploads and deletion | `POST /files`, `DELETE /files` |
|
||
| Web search integration settings and connection tests | `/integrations/web-access` |
|
||
| Sign-in, sessions, profile, passwords, two-factor authentication, passkeys and API keys | `/api/auth/*` (outside `/api/openapi`) |
|
||
|
||
Authentication workflows use Better Auth's native HTTP API and its own error contract. Your instance publishes their specification at `/api/auth/open-api/generate-schema`; use that specification for the enabled authentication methods. Browser interactions such as zoom, print dialogs and local undo do not require separate server endpoints: use document changes, versions and exports for the corresponding data workflows.
|
||
|
||
`GET /api/health` (outside `/api/openapi`) reports whether the instance and its database and storage are healthy. It needs no key.
|
||
|
||
## Imports and exports
|
||
|
||
File imports accept a multipart form. The format is one of `PDF`, `REACTIVE_RESUME`, `REACTIVE_RESUME_V4`, `JSON_RESUME` or `LINKEDIN`; the maximum file size is 10 MiB. PDF imports read the text layer without AI. AI-assisted PDF and Word parsing remain available under `/ai/pdf-parses` and `/ai/docx-parses`; save the resulting data through `/resumes/imports`.
|
||
|
||
```bash
|
||
curl "https://rxresu.me/api/openapi/resumes/file-imports" \
|
||
-H "x-api-key: YOUR_API_KEY" \
|
||
-F "format=JSON_RESUME" -F "file=@resume.json"
|
||
|
||
curl "https://rxresu.me/api/openapi/resumes/RESUME_ID/exports/docx" \
|
||
-H "x-api-key: YOUR_API_KEY" -o resume.docx
|
||
```
|
||
|
||
Exports accept `pdf`, `docx`, `md` or `json` and return a downloadable file. They enforce document ownership. The public checker accepts a multipart `file` (PDF, maximum 25 MB) and optional `jobDescription` text. It stores nothing, examines at most 30 pages and reports truncation or skipped checks. Parsing has a 45-second deadline. Hosting-provider request limits still apply.
|
||
|
||
## Pagination and partial updates
|
||
|
||
Collection endpoints support `limit` (1–100) and `offset` (zero-based). For existing array responses, omitting both preserves the complete array for compatibility. Supplying only `offset` selects a page size of 20. The `X-Total-Count` header reports the total before slicing; paginated responses also include `X-Limit` and `X-Offset`. The cover-letter list retains its existing `{ items, total }` response and default pagination.
|
||
|
||
```bash
|
||
curl "https://rxresu.me/api/openapi/resumes?limit=20&offset=20" \
|
||
-H "x-api-key: YOUR_API_KEY" -i
|
||
```
|
||
|
||
Use `PATCH` for partial application, interview, timeline-entry and cover-letter updates. Resume content uses JSON Patch at `/resumes/{id}`; metadata uses `PATCH /resumes/{id}/metadata`. Resource-oriented paths such as `/resumes/{id}/copies` and `/documents/{type}/{id}/trash` are preferred for new integrations. Existing verb-based routes, partial `PUT` routes, response shapes and enum values remain supported.
|
||
|
||
## Retries
|
||
|
||
State-changing operations do not implement `Idempotency-Key`. Treat mutations as unsafe to retry automatically, including requests that timed out: the change might already have happened. Read the current resource before deciding whether to repeat a write. Repeating create, copy, import or AI operations can create duplicates or incur provider charges.
|
||
|
||
## Authentication methods
|
||
|
||
The API accepts three kinds of credentials:
|
||
|
||
1. `x-api-key: <key>`: an API key from Settings. Use this for scripts and servers.
|
||
2. `Authorization: Bearer <token>`: an OAuth access token, which MCP clients get when you connect them with OAuth. See [Using the MCP server](/guides/using-the-mcp-server).
|
||
3. The session cookie of a signed-in browser.
|
||
|
||
Send one credential. When several are present, the server tries API key, bearer token, then session cookie, using the first valid credential. Cookie-authenticated requests with a foreign `Origin` or cross-site fetch metadata are rejected; explicit API keys and bearer tokens do not rely on browser cookies.
|
||
|
||
A private request without valid credentials gets `401` with the code `UNAUTHORIZED`. Public operations are marked with `security: []` in the OpenAPI specification. Public resumes still enforce visibility, trash status and sharing passwords, and redact private data.
|
||
|
||
REST data responses use `Cache-Control: no-store`. Uploaded profile images are public; other uploaded files require the owner's credentials, including conditional download requests. Assistant attachments are not exposed through the uploads URL. Unknown and unauthorized file URLs return `404`.
|
||
|
||
## Limits
|
||
|
||
| Limit | Value |
|
||
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
|
||
| Requests per API key | 1,000 per hour |
|
||
| Changes to one resume, document or application (create, update, patch, lock, duplicate, delete) | 300 per minute |
|
||
| PDF downloads of one resume (`GET /resumes/{id}/pdf`) | 5 per minute |
|
||
| Public PDF checks per client address | 5 per minute |
|
||
| REST request body size (before endpoint-specific limits) | 40 MiB |
|
||
| AI requests | 20 per minute |
|
||
| Request body size on Vercel installations | 4.5 MB (see [Large RPC requests](/guides/large-rpc-requests)) |
|
||
|
||
Procedure limits apply in production. When you hit a limit, the API responds with `429`. On a self-hosted installation, `FLAG_DISABLE_API_RATE_LIMIT` turns off the per-key limit together with the sign-in limits; the procedure limits also turn off (see [Environment variables](/self-hosting/environment-variables)).
|
||
|
||
## Errors
|
||
|
||
Errors come back as JSON with a machine-readable `code`, the HTTP `status` and a `message`. Validation errors also include the failing fields in `data.issues`.
|
||
|
||
```json
|
||
{ "defined": false, "code": "NOT_FOUND", "status": 404, "message": "Not Found" }
|
||
```
|
||
|
||
Branch on `code` rather than on the message text. Invalid input uses `400`, missing authentication `401`, forbidden actions `403`, missing or inaccessible resources `404`, conflicts `409`, oversized requests `413`, rate limits `429`, and unexpected failures `500`. Unexpected failures do not expose internal exception details.
|
||
|
||
## Revoke a key
|
||
|
||
<Steps>
|
||
<Step title="Find the key">
|
||
Open **Settings**, then **AI & developer**. In the **API keys** table, find the key you want to stop.
|
||
</Step>
|
||
<Step title="Revoke it">
|
||
Select **Revoke**. The key stops working at once, and a message confirms which key you revoked.
|
||
|
||
<Frame caption="Revoking a key shows an Undo action">
|
||
<img src="/images/guides/using-the-api/revoke-key-undo-toast.webp" alt="Message reading Revoked Claude Desktop. Apps using it stop working now, with an Undo link" />
|
||
</Frame>
|
||
|
||
</Step>
|
||
<Step title="Undo if you revoked the wrong key">
|
||
Select **Undo** in the message to turn the key back on. When the message closes, the key is deleted for good.
|
||
</Step>
|
||
</Steps>
|
||
|
||
## The RPC endpoint
|
||
|
||
The web app talks to the server through oRPC at `/api/rpc`, using the same procedures, authorization and validation as the REST API. It uses oRPC's own wire format, and its procedure names follow the app's source code rather than a published contract. For integrations, use the REST API under `/api/openapi`, which has a documented, generated specification.
|
||
|
||
## Changes from v5
|
||
|
||
If you built against the v5 API, check these changes:
|
||
|
||
- **Structured dates.** Dated entries have a `dates` object (`start`, `end`, `present`). The text fields `period` and `date` are still returned, but the server rewrites them from `dates` on every save, so writing only the text has no effect. See [Using the patch API](/guides/using-the-patch-api#dates).
|
||
- **Cover letters are their own documents.** Resumes no longer hold cover letters. Use the `/cover-letters` endpoints. If you send a resume that still contains a cover-letter section (for example an old export), the server saves each letter as a separate cover letter and removes the section from the resume.
|
||
- **Application link.** `GET /resumes/{id}` includes `applicationId` for a tailored resume. Trash and automatic naming remain managed through the documents API.
|
||
- **No cover-letter PDF from resumes.** `GET /resumes/{id}/pdf` only accepts `target=resume` (or no target). Old signed download links that ask for a cover letter return `404`.
|
||
- **Delete moves to Trash.** `DELETE /resumes/{id}` and `DELETE /cover-letters/{id}` move the document to Trash for 30 days. Use the `/documents/restore` and `/documents/purge` endpoints to bring it back or delete it at once.
|
||
- **Application stages.** The `rejected` stage and the `archived` flag are gone. Close an application with the `closed` stage and a `closedReason` (`not-selected`, `withdrew`, `accepted-other` or `no-response`).
|
||
- **Resume versions.** Versions have a `kind` and an optional `name` instead of a free-text label.
|
||
|
||
Self-hosters upgrading an installation can read [Upgrading to v6](/self-hosting/upgrading-to-v6).
|
||
|
||
## Related guides
|
||
|
||
<CardGroup cols={2}>
|
||
<Card title="Using the patch API" href="/guides/using-the-patch-api">
|
||
Change individual fields of a resume with JSON Patch.
|
||
</Card>
|
||
<Card title="Using the MCP server" href="/guides/using-the-mcp-server">
|
||
Let AI clients such as Claude or Cursor work with your documents.
|
||
</Card>
|
||
<Card title="JSON resume schema" href="/guides/json-resume-schema">
|
||
The structure of resume data, for validation and code generation.
|
||
</Card>
|
||
<Card title="Large RPC requests" href="/guides/large-rpc-requests">
|
||
How large request bodies reach Vercel installations.
|
||
</Card>
|
||
</CardGroup>
|