# Authentication

API key and Authorization header for the Rezzy Public API

Source: https://docs.rezzy.dev/authentication
Documentation index: https://docs.rezzy.dev/llms.txt



  Every request must include an API key. Requests without a valid key receive
  **401 Unauthorized**.

## Authorization header

Send your API key in the `Authorization` header:

```
Authorization: Bearer <your_api_key>
```

Replace `<your_api_key>` with the key you create in the Rezzy dashboard.

## Error response

When the header is missing or the API key is invalid or expired, the API returns **401 Unauthorized**.

  API keys are created and managed in the [Rezzy
  dashboard](https://www.rezzy.dev/dashboard/api/keys).



# Error reference

Error envelopes and HTTP status codes for the Rezzy Public API

Source: https://docs.rezzy.dev/errors
Documentation index: https://docs.rezzy.dev/llms.txt



REST errors use the same envelope as successful responses, with `success: false` and an appropriate HTTP status code. MCP tool errors use a different format; see [MCP](https://docs.rezzy.dev/mcp#errors).

## Standard error envelope

```json
{
  "success": false,
  "message": "Human-readable error message",
  "data": {
    "error_code": "BAD_REQUEST",
    "details": {}
  }
}
```

`error_code` identifies the error category. `details` contains additional information when available. Check the HTTP status and error code rather than matching message text.

## Validation errors

Missing required fields, incorrect types, and titles longer than 255 characters return **400 Bad Request**, with `error_code: "BAD_REQUEST"`. Multiple validation messages are joined with `; `.

```json
{
  "success": false,
  "message": "title should not be empty",
  "data": {
    "error_code": "BAD_REQUEST",
    "details": {}
  }
}
```

Business validation also returns **400**, with `error_code: "VALIDATION_ERROR"`: for example, an incomplete profile import, an invalid or unreachable company URL, or an invalid cover letter date.

Unknown request body fields are stripped. Duplicate document titles are resolved by adding a suffix such as `_1`; they do not produce a conflict error.

## HTTP status codes

| Code | Error code                                  | Meaning                                                         |
| ---- | ------------------------------------------- | --------------------------------------------------------------- |
| 200  | —                                           | Status retrieved                                                |
| 202  | —                                           | Generation job accepted                                         |
| 400  | `BAD_REQUEST` or `VALIDATION_ERROR`         | Invalid request, malformed UUID, or business validation failure |
| 401  | `UNAUTHORIZED`                              | Missing or invalid API key                                      |
| 403  | `FORBIDDEN`                                 | Insufficient generation credits                                 |
| 404  | `NOT_FOUND`                                 | Document does not exist or does not belong to your account      |
| 429  | `RATE_LIMIT_EXCEEDED`                       | Request limit exceeded                                          |
| 500  | `INTERNAL_ERROR` or `INTERNAL_SERVER_ERROR` | Server error                                                    |
| 503  | `SERVICE_UNAVAILABLE`                       | Required service unavailable                                    |

## Rate limit errors

```json
{
  "success": false,
  "message": "Too many requests. Please try again later.",
  "data": {
    "error_code": "RATE_LIMIT_EXCEEDED",
    "details": { "retry_after": 45 }
  }
}
```

Wait for the `Retry-After` duration in seconds before retrying. See [Rate limiting](https://docs.rezzy.dev/rate-limiting) for limits and headers.

Creation is not idempotent. If a connection fails after sending a create request, the job may already have been queued and charged. Do not automatically repeat creation after an ambiguous failure; check the dashboard first. Status reads can be retried with backoff.


# Overview

What is Rezzy API and what can it do for you?

Source: https://docs.rezzy.dev/
Documentation index: https://docs.rezzy.dev/llms.txt



Traditionally, [Rezzy](https://rezzy.dev) has been a SaaS web app where you click around a dashboard to get things done. But let's be real, that's not how developers operate. You want to write scripts, automate workflows, plug things into your AI agents, and move fast without touching a UI.

That's exactly why we built the Rezzy API. It's the first API of its kind in the resume tooling space, and we're adding more capabilities over time. Right now, you can programmatically generate resumes and cover letters, with more endpoints on the way.

If you want to skip the intro and just get building, head over to the [Quickstart](https://docs.rezzy.dev/quickstart). Otherwise, keep reading.

## User Profile

To use the Rezzy API, you need a profile set up on the platform. Think of it like a LinkedIn profile - it holds all your information, and your agent refers to it when drafting a resume or cover letter for a specific role.

If you've used [Rezzy](https://rezzy.dev) before, you'll know that the UI lets you either upload a base resume or use your profile as the starting point. The API works the same way, with one difference: **we don't support resume uploads via the API.** Your profile is the only source of truth here.

Your profile import must finish successfully before generation. If you call the API without a completed profile, generation returns a validation error. Head over to [rezzy.dev/dashboard/profile](https://rezzy.dev/dashboard/profile) to get that sorted before making your first request.

## Credits

The Rezzy API is credit-based: generation costs credits (5 for a resume, 3 for a cover letter), while status and documentation reads consume no generation credits. The Free plan includes 25 credits total; the Pro plan includes 1,000 per month. You can also buy credit packs. Purchased credits never expire and are only used after your included credits run out. See [Pricing](https://docs.rezzy.dev/pricing) for full details on plans and credit packs.

## Base URL

The endpoints in this documentation are the public integration routes (`/v1/...`) for programmatic resume and cover letter generation. Send requests to:

```
https://api.rezzy.dev/v1
```

Paths are rooted at that prefix (for example, `POST /resume/create` is `https://api.rezzy.dev/v1/resume/create`).

## Response Format

Every REST response from the Rezzy API follows the same envelope structure:

| Field     | Type      | Description                                                      |
| --------- | --------- | ---------------------------------------------------------------- |
| `success` | `boolean` | `true` on success, `false` on error                              |
| `message` | `string`  | A human-readable message describing the result                   |
| `data`    | `object`  | The response payload on success; error code and details on error |

On errors, the same structure is returned with `success: false` and an appropriate HTTP status code. See the [Error Reference](https://docs.rezzy.dev/errors) for the full list of error codes and what they mean.

## MCP

Connect an AI agent to Rezzy through the [MCP server](https://docs.rezzy.dev/mcp). It exposes resume and cover letter creation, status polling, and a `use_docs` tool for reading additional API documentation when needed.

## Machine-readable documentation

Use [llms.txt](https://docs.rezzy.dev/llms.txt) to discover Markdown pages, or [llms-full.txt](https://docs.rezzy.dev/llms-full.txt) for the complete documentation. Each page also offers **Copy Markdown** and **View as Markdown**.

The [OpenAPI specification](https://docs.rezzy.dev/openapi.json) describes the public REST endpoints under `/v1`, including authentication, request constraints, and response schemas. It is generated from the current backend source. MCP uses its own protocol and is documented separately.


# MCP

Connect an AI agent to Rezzy, read documentation, and generate resumes and cover letters

Source: https://docs.rezzy.dev/mcp
Documentation index: https://docs.rezzy.dev/llms.txt



The Rezzy MCP server exposes the public generation API as tools for AI agents. It uses the same API keys, profile, document ownership, and generation credits as REST.

## Connect

Configure a client that supports remote **Streamable HTTP** servers and custom authorization headers:

| Setting              | Value                          |
| -------------------- | ------------------------------ |
| Server URL           | `https://api.rezzy.dev/v1/mcp` |
| Transport            | Streamable HTTP                |
| Authorization header | `Bearer YOUR_API_KEY`          |

Create your API key in [the dashboard](https://rezzy.dev/dashboard/api/keys). Keep it private and configure it in your client's credentials or headers rather than putting it in prompts. This endpoint uses API key authentication, not OAuth.

The server is stateless and returns JSON responses. Clients should handle MCP initialization and protocol headers. Requests use `POST`; browser preflight uses `OPTIONS`. There is no separate GET event stream or persistent session ID.

Generation requires a [completed profile import](https://rezzy.dev/dashboard/profile) and enough credits. Reading documentation does not require a completed profile, but every tool call requires a valid API key.

## Save tool approvals

After connecting through [the MCP dashboard](https://rezzy.dev/dashboard/api/mcp), you can save permissions in your client to reduce repeated approval prompts. The instructions below cover the four clients offered in the dashboard and assume the server is named `rezzy`.

Approving generation tools lets the client use your profile already stored in Rezzy and spend **5 credits per resume** or **3 credits per cover letter**. These permissions do not set a spending limit. Documentation and status reads cost no generation credits. Repeating a creation call can charge again.

Choose which tools to approve. To keep confirmation for spending credits, approve only `use_docs`, `get_resume`, and `get_cover_letter`. To allow generation too, include `create_resume` and `create_cover_letter`.

### Claude Code

Run `/permissions` and add **Allow** rules for the tools you want to approve:

```text
mcp__rezzy__use_docs
mcp__rezzy__get_resume
mcp__rezzy__get_cover_letter
mcp__rezzy__create_resume
mcp__rezzy__create_cover_letter
```

Save them at the user scope to apply across projects, or at the project scope for the current project. The dialog shows the settings file each rule comes from. Matching **Ask** or **Deny** rules take precedence over Allow rules; review those if prompts persist.

See [Claude Code permissions](https://code.claude.com/docs/en/permissions#manage-permissions) and [MCP rule syntax](https://code.claude.com/docs/en/permissions#mcp).

### Cursor

In **Cursor Settings > Agents > Approvals & Execution**, use the MCP allowlist for tools you want to run without confirmation. In Cursor 3.6 and later, **Auto-review** runs allowlisted calls immediately and reviews other calls; selecting Auto-review alone does not approve every call.

You can also merge these entries into `~/.cursor/permissions.json` for all projects, or `.cursor/permissions.json` for one workspace:

```json
{
  "mcpAllowlist": [
    "rezzy:use_docs",
    "rezzy:get_resume",
    "rezzy:get_cover_letter",
    "rezzy:create_resume",
    "rezzy:create_cover_letter"
  ]
}
```

This file's MCP allowlist replaces the one configured in Cursor's UI. Preserve any existing entries you still need. Cursor reloads the file when it changes; team-admin controls take precedence.

See [Cursor's permissions reference](https://cursor.com/docs/reference/permissions) and [Auto-review behavior](https://cursor.com/changelog/auto-review).

### Codex

For the direct MCP connection configured by the dashboard, add these tool settings to `~/.codex/config.toml`, alongside your existing `[mcp_servers.rezzy]` connection. Merge with any existing tables instead of declaring the same table twice:

```toml
[mcp_servers.rezzy.tools.use_docs]
approval_mode = "approve"

[mcp_servers.rezzy.tools.get_resume]
approval_mode = "approve"

[mcp_servers.rezzy.tools.get_cover_letter]
approval_mode = "approve"

[mcp_servers.rezzy.tools.create_resume]
approval_mode = "approve"

[mcp_servers.rezzy.tools.create_cover_letter]
approval_mode = "approve"
```

These settings apply to the named tools on this connection. Plugin-installed servers use a separate `plugins.<plugin>.mcp_servers.<server>.tools.<tool>.approval_mode` configuration path.

**Approve for me** routes eligible approval requests to an automatic reviewer, which can still deny them. It is not a saved approval for Rezzy. Organization policies still apply.

See [Codex configuration](https://learn.chatgpt.com/docs/config-file/config-reference), [plugin server policy](https://developers.openai.com/plugins/build/plugins#configure-installed-server-policy), and [automatic review](https://learn.chatgpt.com/docs/sandboxing/auto-review).

### VS Code

For GitHub Copilot in VS Code:

1. Open the Command Palette and run **Chat: Manage Tool Approval**.
2. Expand the Rezzy MCP server and enable **without approval** for the tools you want to approve.
3. When granting permission from a tool confirmation, choose the session, workspace, or future-invocations scope that fits your use.

Pre-approval controls whether a tool runs. **Without reviewing result** is a separate permission for adding its response to chat. Tools disabled for auto-approval by your settings or organization still require manual approval. Other agents running inside VS Code may use their own client's permission settings.

See [VS Code tool approvals](https://code.visualstudio.com/docs/agents/run/approvals#manage-tool-approvals).

### If the client still asks

Check that the saved permission matches the server name and tool being called, and that no organization policy overrides it. A tool permission controls execution; the assistant may still ask a question if your requested action or spending authorization is unclear. Rezzy cannot override the client's decision.

For a single request, make the authorization explicit: “Use my saved Rezzy profile to generate one resume and one cover letter for this role. I authorize the 8-credit total.” This clarifies your intent without changing future tool permissions.

Client settings were checked against the linked official documentation on October 11, 2026. Available controls can vary by version and organization policy.

## Tools

| Tool                  | Required arguments         | Credits | Result                                               |
| --------------------- | -------------------------- | ------- | ---------------------------------------------------- |
| `use_docs`            | None; optional `page`      | 0       | Documentation URL and Markdown                       |
| `create_resume`       | `title`, `job_description` | 5       | Job ID, stored `resume_title`, status, dashboard URL |
| `get_resume`          | `resume_id`                | 0       | Status, stage, PDF URL, dashboard URL                |
| `create_cover_letter` | `title`, `job_description` | 3       | Job ID, stored `title`, status, dashboard URL        |
| `get_cover_letter`    | `cover_letter_id`          | 0       | Status, stage, PDF URL, dashboard URL                |

`create_resume` accepts optional `company_url`. `create_cover_letter` also accepts `hiring_manager_name`, `company_street_address`, `company_city`, `company_state`, `company_zip`, `hiring_manager_email`, `date`, and `additional_context`. See [Create resume](https://docs.rezzy.dev/resume/create) and [Create cover letter](https://docs.rezzy.dev/cover-letter/create) for field constraints.

Status tools only return documents belonging to the account that owns your key. Creation is not idempotent: repeating a call can queue another job and deduct credits again. Duplicate titles receive suffixes such as `_1`.

## Read docs with use_docs

The tool descriptions contain the standard generation workflow. Call `use_docs` when additional API details are needed. It reads the selected page from the official docs site and returns its Markdown, so the agent can check required fields and behavior.

Example tool call (your MCP client handles the protocol):

```json
{
  "name": "use_docs",
  "arguments": { "page": "resume/create" }
}
```

The optional `page` defaults to `mcp`. Supported values are:

* `overview`
* `quickstart`
* `mcp`
* `authentication`
* `pricing`
* `rate-limiting`
* `errors`
* `resume/create`
* `resume/get-status`
* `cover-letter/create`
* `cover-letter/get-status`

Successful tool results contain `structuredContent`, plus a text content block containing the same data as JSON. For `use_docs`, the data has this shape:

```json
{
  "url": "https://docs.rezzy.dev/resume/create",
  "markdown": "# Create resume\n..."
}
```

Documentation reads consume no generation credits and count toward [MCP request limits](https://docs.rezzy.dev/rate-limiting#mcp-limits). If the docs site is unavailable, the tool returns an error.

## Generation workflow

1. Call `create_resume` or `create_cover_letter` with the job description and title. Save each returned `id`. When both are requested, track the jobs independently.
2. Tell the user generation has started: a resume normally takes about a minute, and a cover letter about 30 seconds. Announce this estimate once. These are typical times, not guarantees or countdowns; generation may take longer.
3. Poll the corresponding status tool after at least `poll_after_seconds`. Back off when status is unchanged and honor HTTP `Retry-After`. Report meaningful stage changes, not every poll.
4. Stop on `SUCCESS` or `FAILED`. Deliver each successful original PDF using `pdf_url`, alongside `dashboard_url`. Explain any failure without automatically creating another document.

Generation uses the authenticated account's completed profile **already stored in Rezzy**, together with the supplied job description. The client does not retrieve or upload a profile from ChatGPT, Codex, or another service. Rezzy requires no separate confirmation for using this saved profile when the user requests generation. Client approval policies still apply. A resume costs 5 credits and a cover letter costs 3 credits.

Example request: “Use Rezzy to generate a resume and cover letter for this role.”

Rezzy handles writing, formatting, and PDF generation. The returned PDF is the finished deliverable. Do not rewrite, reformat, convert, or run a local PDF review unless the user requests it. Download an unchanged copy only when requested or needed for delivery.

### Progress and delivery fields

These fields supplement the existing MCP creation and status results; the REST response format is unchanged.

| Field                | Meaning                                                                                                              |
| -------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `poll_after_seconds` | Minimum delay before the next status read (currently 5 seconds); `null` on terminal states. Back off when unchanged. |
| `stage`              | Status results only: current generation stage, or `null` when unavailable or complete.                               |
| `pdf_url`            | Status results only: original finished PDF URL, or `null` until available.                                           |
| `pdf_url_expires_at` | Status results only: ISO 8601 signed-link expiration, or `null` when no signed PDF link is available.                |
| `dashboard_url`      | Dashboard link for accessing saved documents.                                                                        |

Signed PDF links expire after one hour. The saved document does not expire with the link. Another status read returns a fresh link without consuming generation credits; expiry does not require downloading, rebuilding, or regenerating the document.

If a create call times out or loses its response, check the dashboard before creating again. The first call may already have queued and charged for a document.

## Errors

MCP tool results do not use the REST `success`, `message`, `data` envelope. Failed tool execution returns `isError: true`, with a text content block containing a JSON error object:

```json
{
  "isError": true,
  "content": [
    {
      "type": "text",
      "text": "{\"error_code\":\"VALIDATION_ERROR\",\"message\":\"Profile import is not complete\"}"
    }
  ]
}
```

The message above is illustrative. Invalid tool arguments are rejected by MCP schema validation. Missing or invalid credentials return HTTP 401 with a JSON-RPC error and a `WWW-Authenticate: Bearer` header. HTTP 429 comes from the rate limiter before tool execution and uses the [rate limit envelope](https://docs.rezzy.dev/rate-limiting#http-429-response).

Handle errors before reading `structuredContent`. Status reads and documentation reads can be retried with backoff; avoid automatically retrying generation after ambiguous failures.


# Pricing & Credits

How credits work, plan allowances, and credit packs.

Source: https://docs.rezzy.dev/pricing
Documentation index: https://docs.rezzy.dev/llms.txt



The Rezzy API runs on a credit-based system. Generation operations cost credits. Status reads and the MCP `use_docs` tool do not consume generation credits.

## Cost per operation

| Operation               | Credits   |
| ----------------------- | --------- |
| Resume generation       | 5 credits |
| Cover letter generation | 3 credits |

## Plans and included credits

**Free plan**: 25 credits total. These credits do not refresh; once you use them, they are gone unless you purchase more or upgrade to Pro.

**Pro plan**: 1,000 credits per month. These credits refresh every month and reset to 1,000 at the start of each billing period. Unused included credits do not carry over to the next month.

## Purchased credits

Both Free and Pro users can purchase additional credit packs at any time. Purchased credits do not expire. They remain in your account until you use them.

Included credits (your plan allowance) are always used first. Purchased credits are only consumed after you have exhausted all your included credits.

To buy credits and see current pack prices, visit [Purchase Credits](https://rezzy.dev/dashboard/api/purchase-credits) on the dashboard. REST and MCP generation use the same credit balance and costs.


# Quick Start

Up and Running in Minutes

Source: https://docs.rezzy.dev/quickstart
Documentation index: https://docs.rezzy.dev/llms.txt



Let's get you up and running with the Rezzy API. This guide walks you through generating your first resume and cover letter from scratch.

## 1. Get an API Key

Create an account on [Rezzy](https://rezzy.dev) and head to [dashboard/api/keys](https://www.rezzy.dev/dashboard/api/keys) to create your first key.

Screenshot: API Keys

Click **Create your first API Key** and give it a name.

Screenshot: Create API Key

Copy your API key and store it somewhere safe. You will need it for every request.

Screenshot: Copy API Key

## 2. Set Up Your Profile

Before making any API calls, make sure you have a profile set up at [rezzy.dev/dashboard/profile](https://rezzy.dev/dashboard/profile). The API uses your profile as the source of truth when generating resumes and cover letters. Wait until the profile import finishes successfully. Missing, failed, or in-progress imports prevent generation.

Screenshot: Create Profile

## 3. Create a Resume or Cover Letter

### Example: Create a resume

  

  
```bash
curl -X POST https://api.rezzy.dev/v1/resume/create \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Senior Software Engineer",
    "job_description": "We are looking for a senior engineer with 5+ years of experience in Python and distributed systems.",
    "company_url": "https://acme.com"
  }'
```
  

  
```python
import requests

response = requests.post(
"https://api.rezzy.dev/v1/resume/create",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"title": "Senior Software Engineer",
"job_description": "We are looking for a senior engineer with 5+ years of experience in Python and distributed systems.",
"company_url": "https://acme.com",
},
)
print(response.json())

```
  

  
```javascript
const response = await fetch("https://api.rezzy.dev/v1/resume/create", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Senior Software Engineer",
    job_description:
      "We are looking for a senior engineer with 5+ years of experience in Python and distributed systems.",
    company_url: "https://acme.com",
  }),
});
const data = await response.json();
console.log(data);
```
  

**Sample response (202 Accepted):**

```json
{
  "success": true,
  "message": "Resume creation job has been successfully registered.",
  "data": {
    "id": "4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b",
    "resume_title": "Senior Software Engineer",
    "status": "QUEUED",
    "dashboard_url": "https://rezzy.dev/dashboard/resumes"
  }
}
```

### Example: Create a cover letter

  

  
```bash
curl -X POST https://api.rezzy.dev/v1/cover-letter/create \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Software Engineer at Acme Corp",
    "job_description": "Full-time role. Requirements: 3+ years Python, REST APIs.",
    "company_url": "https://acme.com",
    "hiring_manager_name": "Jane Smith",
    "company_city": "San Francisco",
    "company_state": "CA",
    "company_zip": "94105",
    "date": "2026-04-09"
  }'
```
  

  
```python
import requests

response = requests.post(
"https://api.rezzy.dev/v1/cover-letter/create",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"title": "Software Engineer at Acme Corp",
"job_description": "Full-time role. Requirements: 3+ years Python, REST APIs.",
"company_url": "https://acme.com",
"hiring_manager_name": "Jane Smith",
"company_city": "San Francisco",
"company_state": "CA",
"company_zip": "94105",
"date": "2026-04-09",
},
)
print(response.json())

```
  

  
```javascript
const response = await fetch(
  "https://api.rezzy.dev/v1/cover-letter/create",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      title: "Software Engineer at Acme Corp",
      job_description:
        "Full-time role. Requirements: 3+ years Python, REST APIs.",
      company_url: "https://acme.com",
      hiring_manager_name: "Jane Smith",
      company_city: "San Francisco",
      company_state: "CA",
      company_zip: "94105",
      date: "2026-04-09",
    }),
  },
);
const data = await response.json();
console.log(data);
```
  

**Sample response (202 Accepted):**

```json
{
  "success": true,
  "message": "Cover letter creation job has been successfully registered.",
  "data": {
    "id": "3de8fcc3-a913-413d-acdb-382701542cb9",
    "title": "Software Engineer at Acme Corp",
    "status": "QUEUED",
    "dashboard_url": "https://rezzy.dev/dashboard/cover-letters"
  }
}
```

## 4. Poll for Completion and Get the PDF

Both resume and cover letter generation are async. After creating a job, poll the status endpoint using the `id` from the create response until `status` is `SUCCESS` or `FAILED`. Poll no faster than every five seconds, back off, and honor `Retry-After` on HTTP 429. On success, use `pdf_url` to download the PDF; it expires after one hour, and another status read returns a fresh URL.

Do not automatically retry a create request after a timeout or lost response: the job may already have been queued and charged. Check the dashboard before creating another document.

### Example: Poll for resume status

  

  
```bash
curl -X GET "https://api.rezzy.dev/v1/resume/4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b" \
  -H "Authorization: Bearer YOUR_API_KEY"
```
  

  
```python
import requests

resume_id = "4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b"
response = requests.get(
f"https://api.rezzy.dev/v1/resume/{resume_id}",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(response.json())

```
  

  
```typescript
const resumeId = "4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b";
const response = await fetch(
  `https://api.rezzy.dev/v1/resume/${resumeId}`,
  {
    method: "GET",
    headers: { Authorization: "Bearer YOUR_API_KEY" },
  },
);
const data = await response.json();
console.log(data);
```
  

**Sample response (while processing):**

```json
{
  "success": true,
  "message": "Resume status retrieved successfully",
  "data": {
    "id": "4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b",
    "resume_title": "Senior Software Engineer",
    "status": "IN_PROGRESS",
    "stage": "Analyzing resume and job description...",
    "pdf_url": null,
    "dashboard_url": "https://rezzy.dev/dashboard/resumes"
  }
}
```

### Example: Poll for cover letter status

  

  
```bash
curl -X GET "https://api.rezzy.dev/v1/cover-letter/3de8fcc3-a913-413d-acdb-382701542cb9" \
  -H "Authorization: Bearer YOUR_API_KEY"
```
  

  
```python
import requests

cover_letter_id = "3de8fcc3-a913-413d-acdb-382701542cb9"
response = requests.get(
f"https://api.rezzy.dev/v1/cover-letter/{cover_letter_id}",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(response.json())

```
  

  
```typescript
const coverLetterId = "3de8fcc3-a913-413d-acdb-382701542cb9";
const response = await fetch(
  `https://api.rezzy.dev/v1/cover-letter/${coverLetterId}`,
  {
    method: "GET",
    headers: { Authorization: "Bearer YOUR_API_KEY" },
  },
);
const data = await response.json();
console.log(data);
```
  

**Sample response (while processing):**

```json
{
  "success": true,
  "message": "Cover letter status retrieved successfully",
  "data": {
    "id": "3de8fcc3-a913-413d-acdb-382701542cb9",
    "title": "Software Engineer at Acme Corp",
    "status": "IN_PROGRESS",
    "stage": "Drafting your cover letter...",
    "pdf_url": null,
    "dashboard_url": "https://rezzy.dev/dashboard/cover-letters"
  }
}
```

Before you start building, review [Rate Limiting](https://docs.rezzy.dev/rate-limiting) and the [Response Format](https://docs.rezzy.dev/#response-format) so you know how to handle limits and errors correctly.


# Rate limiting

REST and MCP request limits, response headers, and retry behavior

Source: https://docs.rezzy.dev/rate-limiting
Documentation index: https://docs.rezzy.dev/llms.txt



Request limits are separate from generation credits. Status reads and documentation tools cost no generation credits but still count toward request limits.

## REST limits

REST requests pass through three layers in order: IP address, API key, then account. A limit at any layer returns HTTP 429.

| Layer      | Free        | Pro         | Window     |
| ---------- | ----------- | ----------- | ---------- |
| IP address | 60 requests | 60 requests | 60 seconds |
| API key    | 10 requests | 20 requests | 60 seconds |
| Account    | 60 requests | 60 requests | 60 seconds |

The account limit is shared by keys belonging to the same account. Requests with missing or invalid credentials still count toward the IP limit; a supplied bearer key also counts toward its key limit. The account layer applies when the key identifies a valid account.

## MCP limits

The [MCP endpoint](https://docs.rezzy.dev/mcp) uses separate windows from REST:

| Layer      | Limit        | Window     |
| ---------- | ------------ | ---------- |
| IP address | 600 requests | 60 seconds |
| API key    | 600 requests | 60 seconds |

MCP limits are the same across plans and do not have an account layer. Protocol requests, tool discovery, documentation reads, and status polling count toward these limits. `OPTIONS` requests are excluded.

## Response headers

| Header                  | Description                                       |
| ----------------------- | ------------------------------------------------- |
| `X-RateLimit-Remaining` | Requests left in the last layer checked           |
| `X-RateLimit-Reset`     | Unix timestamp in seconds when that window resets |
| `Retry-After`           | On HTTP 429, seconds to wait before retrying      |

These headers report the last layer checked, rather than every layer's remaining quota.

## HTTP 429 response

REST and MCP requests rejected by the rate limiter receive this HTTP JSON body before any tool executes:

```json
{
  "success": false,
  "message": "Too many requests. Please try again later.",
  "data": {
    "error_code": "RATE_LIMIT_EXCEEDED",
    "details": { "retry_after": 45 }
  }
}
```

The response includes `Retry-After`, `X-RateLimit-Remaining: 0`, and `X-RateLimit-Reset`. Honor `Retry-After`, poll generation status no faster than every five seconds, and back off between reads. Do not automatically repeat a creation request after an ambiguous connection failure: it can create and charge for a second document.


# Create cover letter

POST /cover-letter/create - queue a cover letter generation job

Source: https://docs.rezzy.dev/cover-letter/create
Documentation index: https://docs.rezzy.dev/llms.txt



## Example

  

  
```bash
curl -X POST https://api.rezzy.dev/v1/cover-letter/create \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Software Engineer at Acme Corp",
    "job_description": "Full-time role. Requirements: 3+ years Python, REST APIs.",
    "company_url": "https://acme.com",
    "hiring_manager_name": "Jane Smith",
    "company_street_address": "123 Main St",
    "company_city": "San Francisco",
    "company_state": "CA",
    "company_zip": "94105",
    "hiring_manager_email": "jane@acme.com",
    "date": "2026-04-09",
    "additional_context": "Referred by John Doe"
  }'
```
  

  
```python
import requests

response = requests.post(
"https://api.rezzy.dev/v1/cover-letter/create",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"title": "Software Engineer at Acme Corp",
"job_description": "Full-time role. Requirements: 3+ years Python, REST APIs.",
"company_url": "https://acme.com",
"hiring_manager_name": "Jane Smith",
"company_street_address": "123 Main St",
"company_city": "San Francisco",
"company_state": "CA",
"company_zip": "94105",
"hiring_manager_email": "jane@acme.com",
"date": "2026-04-09",
"additional_context": "Referred by John Doe",
},
)
print(response.json())

```
  

  
```javascript
const response = await fetch(
  "https://api.rezzy.dev/v1/cover-letter/create",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      title: "Software Engineer at Acme Corp",
      job_description:
        "Full-time role. Requirements: 3+ years Python, REST APIs.",
      company_url: "https://acme.com",
      hiring_manager_name: "Jane Smith",
      company_street_address: "123 Main St",
      company_city: "San Francisco",
      company_state: "CA",
      company_zip: "94105",
      hiring_manager_email: "jane@acme.com",
      date: "2026-04-09",
      additional_context: "Referred by John Doe",
    }),
  },
);
const data = await response.json();
console.log(data);
```
  

**Sample response (202 Accepted):**

```json
{
  "success": true,
  "message": "Cover letter creation job has been successfully registered.",
  "data": {
    "id": "3de8fcc3-a913-413d-acdb-382701542cb9",
    "title": "Software Engineer at Acme Corp",
    "status": "QUEUED",
    "dashboard_url": "https://rezzy.dev/dashboard/cover-letters"
  }
}
```

  Processing is asynchronous. Use the returned `id` with [Get cover letter
  status](https://docs.rezzy.dev/cover-letter/get-status) to poll for completion.

## Request body

| Field                    | Type   | Required | Constraints                       | Example                                                               |
| ------------------------ | ------ | -------- | --------------------------------- | --------------------------------------------------------------------- |
| `title`                  | string | Yes      | 1–255 characters                  | `"Software Engineer – Acme Corp"`                                     |
| `job_description`        | string | Yes      | Min length 1                      | `"Full-time role in San Francisco. Requirements: 3+ years Python..."` |
| `company_url`            | string | No       | Max length 500                    | `"https://acme.com"`                                                  |
| `hiring_manager_name`    | string | No       | -                                 | `"Jane Smith"`                                                        |
| `company_street_address` | string | No       | -                                 | `"123 Main St"`                                                       |
| `company_city`           | string | No       | -                                 | `"San Francisco"`                                                     |
| `company_state`          | string | No       | -                                 | `"CA"`                                                                |
| `company_zip`            | string | No       | -                                 | `"94105"`                                                             |
| `hiring_manager_email`   | string | No       | -                                 | `"jane@acme.com"`                                                     |
| `date`                   | string | No       | Valid calendar date, `YYYY-MM-DD` | `"2026-04-09"`                                                        |
| `additional_context`     | string | No       | -                                 | `"Referred by John Doe"`                                              |

  Including `company_url` helps tailor the letter to the employer. When
  provided, Rezzy can research the company and role context similarly to the
  dashboard flow.

Your profile import must be complete before generation. Unknown fields are stripped, and optional fields can be omitted or set to `null`.

A supplied company URL must be a reachable public HTTP or HTTPS website, at most 500 characters. A bare hostname is accepted and prefixed with `https://`; private network addresses are rejected.

The optional `date` must be a valid calendar date. Single-digit months and days are normalized to `YYYY-MM-DD`; an omitted or blank date is left unset.

Duplicate titles are automatically renamed with suffixes such as `_1`. Read the stored title from the response. Each create call can queue and charge for a new document; do not automatically retry an ambiguous failure.

## Success response (202 Accepted)

`data`:

| Field           | Type   | Description                                             |
| --------------- | ------ | ------------------------------------------------------- |
| `id`            | UUID   | Cover letter resource ID                                |
| `title`         | string | Stored title, with a suffix if the title already exists |
| `status`        | string | One of: `QUEUED`, `IN_PROGRESS`, `SUCCESS`, `FAILED`    |
| `dashboard_url` | string | URL to view in the dashboard                            |

## Error responses

| Status | Condition                                                                                              |
| ------ | ------------------------------------------------------------------------------------------------------ |
| 400    | Invalid request fields, incomplete profile import, or invalid/unreachable company URL, or invalid date |
| 401    | Missing or invalid API key                                                                             |
| 403    | Insufficient credits                                                                                   |
| 429    | Request limit exceeded                                                                                 |
| 500    | Internal server error                                                                                  |

See [Errors](https://docs.rezzy.dev/errors) for response bodies and [Rate limiting](https://docs.rezzy.dev/rate-limiting) for retry headers.


# Get cover letter status

GET /cover-letter/{cover_letter_id} - status and PDF URL for a cover letter

Source: https://docs.rezzy.dev/cover-letter/get-status
Documentation index: https://docs.rezzy.dev/llms.txt



## Example

  

  
```bash
curl -X GET "https://api.rezzy.dev/v1/cover-letter/3de8fcc3-a913-413d-acdb-382701542cb9" \
  -H "Authorization: Bearer YOUR_API_KEY"
```
  

  
```python
import requests

cover_letter_id = "3de8fcc3-a913-413d-acdb-382701542cb9"
response = requests.get(
f"https://api.rezzy.dev/v1/cover-letter/{cover_letter_id}",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(response.json())

```
  

  
```typescript
const coverLetterId = "3de8fcc3-a913-413d-acdb-382701542cb9";
const response = await fetch(
  `https://api.rezzy.dev/v1/cover-letter/${coverLetterId}`,
  {
    method: "GET",
    headers: { Authorization: "Bearer YOUR_API_KEY" },
  },
);
const data = await response.json();
console.log(data);
```
  

**Sample response (while processing):**

```json
{
  "success": true,
  "message": "Cover letter status retrieved successfully",
  "data": {
    "id": "3de8fcc3-a913-413d-acdb-382701542cb9",
    "title": "Software Engineer at Acme Corp",
    "status": "IN_PROGRESS",
    "stage": "Drafting your cover letter...",
    "pdf_url": null,
    "dashboard_url": "https://rezzy.dev/dashboard/cover-letters"
  }
}
```

**Sample response (completed):**

```json
{
  "success": true,
  "message": "Cover letter status retrieved successfully",
  "data": {
    "id": "3de8fcc3-a913-413d-acdb-382701542cb9",
    "title": "Software Engineer at Acme Corp",
    "status": "SUCCESS",
    "stage": null,
    "pdf_url": "https://storage.example.com/cover-letters/3de8fcc3.pdf",
    "dashboard_url": "https://rezzy.dev/dashboard/cover-letters"
  }
}
```

## Path parameters

| Parameter         | Type | Required | Description                          | Example                                |
| ----------------- | ---- | -------- | ------------------------------------ | -------------------------------------- |
| `cover_letter_id` | UUID | Yes      | Cover letter ID from create response | `660e8400-e29b-41d4-a716-446655440001` |

## Success response (200 OK)

`data`:

| Field           | Type           | Description                                                  |
| --------------- | -------------- | ------------------------------------------------------------ |
| `id`            | UUID           | Cover letter resource ID                                     |
| `title`         | string         | Cover letter title                                           |
| `status`        | string         | `QUEUED` \| `IN_PROGRESS` \| `SUCCESS` \| `FAILED`           |
| `stage`         | string \| null | Processing stage while queued or in progress; otherwise null |
| `pdf_url`       | string \| null | Signed PDF URL when successful and available; otherwise null |
| `dashboard_url` | string         | URL to view in the dashboard                                 |

Poll no faster than every five seconds and back off. Stop polling on `SUCCESS` or `FAILED`. Both `stage` and `pdf_url` are always included and may be `null`.

PDF URLs expire after one hour. Read status again to get a fresh URL. Status reads do not consume generation credits. You can only retrieve documents belonging to the account that owns your API key.

## Error responses

| Status | Condition                                        |
| ------ | ------------------------------------------------ |
| 400    | Malformed document UUID                          |
| 401    | Missing or invalid API key                       |
| 404    | Document not found or belongs to another account |
| 429    | Request limit exceeded                           |
| 500    | Internal server error                            |


# Create resume

POST /resume/create - queue a resume generation job

Source: https://docs.rezzy.dev/resume/create
Documentation index: https://docs.rezzy.dev/llms.txt



## Example

  

  
```bash
curl -X POST https://api.rezzy.dev/v1/resume/create \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Senior Software Engineer",
    "job_description": "We are looking for a senior engineer with 5+ years of experience in Python and distributed systems.",
    "company_url": "https://acme.com"
  }'
```
  

  
```python
import requests

response = requests.post(
"https://api.rezzy.dev/v1/resume/create",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"title": "Senior Software Engineer",
"job_description": "We are looking for a senior engineer with 5+ years of experience in Python and distributed systems.",
"company_url": "https://acme.com",
},
)
print(response.json())

```
  

  
```javascript
const response = await fetch("https://api.rezzy.dev/v1/resume/create", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Senior Software Engineer",
    job_description:
      "We are looking for a senior engineer with 5+ years of experience in Python and distributed systems.",
    company_url: "https://acme.com",
  }),
});
const data = await response.json();
console.log(data);
```
  

**Sample response (202 Accepted):**

```json
{
  "success": true,
  "message": "Resume creation job has been successfully registered.",
  "data": {
    "id": "4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b",
    "resume_title": "Senior Software Engineer",
    "status": "QUEUED",
    "dashboard_url": "https://rezzy.dev/dashboard/resumes"
  }
}
```

  Processing is asynchronous. Use the returned `id` with [Get resume
  status](https://docs.rezzy.dev/resume/get-status) to poll for completion.

## Request body

| Field             | Type   | Required | Constraints      | Example                                                   |
| ----------------- | ------ | -------- | ---------------- | --------------------------------------------------------- |
| `title`           | string | Yes      | 1–255 characters | `"Senior Software Engineer"`                              |
| `job_description` | string | Yes      | Min length 1     | `"We are looking for a senior engineer with 5+ years..."` |
| `company_url`     | string | No       | Max length 500   | `"https://acme.com"`                                      |

  Including `company_url` provides company context for tailoring the resume.

Your profile import must be complete before generation. Unknown fields are stripped, and optional fields can be omitted or set to `null`.

A supplied company URL must be a reachable public HTTP or HTTPS website, at most 500 characters. A bare hostname is accepted and prefixed with `https://`; private network addresses are rejected.

Duplicate titles are automatically renamed with suffixes such as `_1`. Read the stored title from the response. Each create call can queue and charge for a new document; do not automatically retry an ambiguous failure.

## Success response (202 Accepted)

`data`:

| Field           | Type   | Description                                             |
| --------------- | ------ | ------------------------------------------------------- |
| `id`            | UUID   | Resume resource ID                                      |
| `resume_title`  | string | Stored title, with a suffix if the title already exists |
| `status`        | string | One of: `QUEUED`, `IN_PROGRESS`, `SUCCESS`, `FAILED`    |
| `dashboard_url` | string | URL to view the resume in the dashboard                 |

## Error responses

| Status | Condition                                                                             |
| ------ | ------------------------------------------------------------------------------------- |
| 400    | Invalid request fields, incomplete profile import, or invalid/unreachable company URL |
| 401    | Missing or invalid API key                                                            |
| 403    | Insufficient credits                                                                  |
| 429    | Request limit exceeded                                                                |
| 500    | Internal server error                                                                 |

See [Errors](https://docs.rezzy.dev/errors) for response bodies and [Rate limiting](https://docs.rezzy.dev/rate-limiting) for retry headers.


# Get resume status

GET /resume/{resume_id} - status and PDF URL for a resume

Source: https://docs.rezzy.dev/resume/get-status
Documentation index: https://docs.rezzy.dev/llms.txt



## Example

  

  
```bash
curl -X GET "https://api.rezzy.dev/v1/resume/4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b" \
  -H "Authorization: Bearer YOUR_API_KEY"
```
  

  
```python
import requests

resume_id = "4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b"
response = requests.get(
f"https://api.rezzy.dev/v1/resume/{resume_id}",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(response.json())

```
  

  
```typescript
const resumeId = "4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b";
const response = await fetch(
  `https://api.rezzy.dev/v1/resume/${resumeId}`,
  {
    method: "GET",
    headers: { Authorization: "Bearer YOUR_API_KEY" },
  },
);
const data = await response.json();
console.log(data);
```
  

**Sample response (while processing):**

```json
{
  "success": true,
  "message": "Resume status retrieved successfully",
  "data": {
    "id": "4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b",
    "resume_title": "Senior Software Engineer",
    "status": "IN_PROGRESS",
    "stage": "Analyzing resume and job description...",
    "pdf_url": null,
    "dashboard_url": "https://rezzy.dev/dashboard/resumes"
  }
}
```

**Sample response (completed):**

```json
{
  "success": true,
  "message": "Resume status retrieved successfully",
  "data": {
    "id": "4c20b695-c3ed-4dc4-bcf3-f6f7aa00068b",
    "resume_title": "Senior Software Engineer",
    "status": "SUCCESS",
    "stage": null,
    "pdf_url": "https://storage.example.com/resumes/4c20b695.pdf",
    "dashboard_url": "https://rezzy.dev/dashboard/resumes"
  }
}
```

## Path parameters

| Parameter   | Type | Required | Description                    | Example                                |
| ----------- | ---- | -------- | ------------------------------ | -------------------------------------- |
| `resume_id` | UUID | Yes      | Resume ID from create response | `550e8400-e29b-41d4-a716-446655440000` |

## Success response (200 OK)

`data`:

| Field           | Type           | Description                                                  |
| --------------- | -------------- | ------------------------------------------------------------ |
| `id`            | UUID           | Resume resource ID                                           |
| `resume_title`  | string         | Resume title                                                 |
| `status`        | string         | `QUEUED` \| `IN_PROGRESS` \| `SUCCESS` \| `FAILED`           |
| `stage`         | string \| null | Processing stage while queued or in progress; otherwise null |
| `pdf_url`       | string \| null | Signed PDF URL when successful and available; otherwise null |
| `dashboard_url` | string         | URL to view in the dashboard                                 |

Poll no faster than every five seconds and back off. Stop polling on `SUCCESS` or `FAILED`. Both `stage` and `pdf_url` are always included and may be `null`.

PDF URLs expire after one hour. Read status again to get a fresh URL. Status reads do not consume generation credits. You can only retrieve documents belonging to the account that owns your API key.

## Error responses

| Status | Condition                                        |
| ------ | ------------------------------------------------ |
| 400    | Malformed document UUID                          |
| 401    | Missing or invalid API key                       |
| 404    | Document not found or belongs to another account |
| 429    | Request limit exceeded                           |
| 500    | Internal server error                            |
