API Reference

Send a resume, receive structured JSON. One schema, one integration.

Base URLhttps://api.resumeparsing.ai/v1
Overview

Introduction

Resume parsing and nothing else — no matching, no scoring, no hiring workflow. Submit a PDF, DOC, DOCX, TXT or HTML file and collect structured data when it is ready.

Parsing is asynchronous. You get an id immediately and collect the result by polling or webhook, so there is no connection to hold open and nothing is lost if a client disconnects.

Response envelopes

Every response is wrapped. Success:

json
{ "success": true, "data": { ... } }

Error:

json
{
  "success": false,
  "error": { "code": "invalid_api_key", "message": "..." }
}
Security

Authentication

Authenticate every request with your workspace API key, sent as a Bearer token of the form identifier:secret (split on the first colon). X-API-Key is also accepted.

http
Authorization: Bearer rp_live_1a2b3c4d5e6f7a8b:9f3c...<48 hex secret>
Your secret is shown only once, at key creation, so store it securely. Rotating a key immediately invalidates the old one.

Authentication failures are deliberately uniform: missing, malformed, unknown, revoked or suspended all return the same 401 invalid_api_key. Anything finer would tell an attacker which half of the credential was right.

Reference

Errors

Errors use standard HTTP status codes and a stable machine-readable code in the error envelope.

HTTPCodeWhen
400invalid_requestMissing or malformed parameter.
401invalid_api_keyKey missing, malformed, unknown, revoked, or workspace suspended. All identical.
402insufficient_creditsWorkspace credit balance is zero or below.
404not_foundUnknown id, or an id owned by another workspace (never 403).
413batch_too_largeMore than 200 files or over 500 MB in one batch.
422unreadable_fileEmpty, oversized, or not a recognised resume format.
429rate_limitedOver the workspace rate limit. Carries a Retry-After header.
5xxinternal_errorUnexpected. Generic message that never leaks internals.
Endpoint

Submit a resume

POST/v1/resumes

Upload a single resume as multipart/form-data. The request is admitted (rate limit, credits, file size, magic byte type check), the file is stored, and a job is queued. The connection closes immediately and nobody waits.

FieldTypeDescription
filefilePDF, DOC, DOCX, TXT or HTML. Up to 10 MB.
external_refstringUp to 512 chars. Stored and echoed verbatim, never interpreted, so thread your own requisition / client / office id through it and route on it when the result comes back.
expiry_timeISO 8601Must be in the future. Defaults to now + 30 days retention.

Required

Example request

bash
curl -X POST https://api.resumeparsing.ai/v1/resumes \
  -H "Authorization: Bearer rp_live_1a2b3c4d5e6f7a8b:<secret>" \
  -F "file=@cv.pdf" \
  -F "external_ref=deloitte/bangalore/req-4471"

Response · 202 Accepted

json
{
  "success": true,
  "data": {
    "id": "res_9f2a4c81",
    "status": "queued",
    "external_ref": "deloitte/bangalore/req-4471",
    "batch_id": null,
    "file_name": "cv.pdf",
    "failure_reason": null,
    "submitted_at": "2026-07-24T10:42:00Z",
    "parsed_at": null
  }
}
Endpoint

Retrieve a resume

GET/v1/resumes/:id

Fetch a job by id. While it is in flight you get the status envelope above. Once status is parsed, the response additionally carries the full data payload (see Output schema) and a non-null parsed_at. A failed job carries a failure_reason and no data.

bash
curl https://api.resumeparsing.ai/v1/resumes/res_9f2a4c81 \
  -H "Authorization: Bearer rp_live_1a2b3c4d5e6f7a8b:<secret>"
Endpoint

Delete a resume

DELETE/v1/resumes/:id

Permanently deletes the resume and every artefact derived from it: the stored file, the job row, the extracted text and any staged fields. Everything derived from the PDF is personal data, so deletion is complete. This cannot be undone.

Endpoint

Batches

Batch endpoints are designed and on the roadmap. Each resume in a batch still carries its own id and external_ref, so you route results exactly as for single submissions.
POST/v1/batchesComing soon
GET/v1/batches/:idComing soon
GET/v1/batches/:id/resultsComing soon

Submit up to 200 resumes (500 MB) in one request and track them together. A batch.completed webhook fires when the whole batch finishes.

Delivery

Webhooks

A webhook is a doorbell, not a delivery truck. It carries ids only, and you then fetch the data yourself. This keeps every notification tiny and always deliverable, and because the result is already stored, a failed delivery loses nothing.

Events: resume.parsed, resume.failed, batch.completed. Each is signed with HMAC-SHA256 over the raw body (X-Signature), using a per-endpoint secret shown once. Deliveries retry with exponential backoff for ~24 h; a stable event_id lets you dedupe.

json
{
  "event": "resume.parsed",
  "event_id": "evt_7c1a9b2f",
  "created_at": "2026-07-24T10:45:12Z",
  "data": {
    "id": "res_9f2a4c81",
    "batch_id": null,
    "external_ref": "deloitte/bangalore/req-4471",
    "status": "parsed"
  }
}
Concepts

Resume lifecycle

A resume moves through four public statuses. The internal pipeline stages are never exposed.

queued

Accepted and waiting to be processed.

processing

Text is being extracted and fields parsed.

parsed

Done. The data payload is available.

failed

Could not be parsed. Carries a failure_reason. You are not charged.

Billing is prepaid: 1 credit = 1 parsed resume, in either mode. A credit is held when you submit and only spent once the parse succeeds — a failed or unreadable resume costs nothing and its credit returns to your balance. Charging is idempotent, so a retried webhook can never double-bill.

Contract

Output schema

One canonical schema for every customer. Conventions: snake_case throughout · a missing value is null (never an empty string) · a missing list is [] · dates are ISO YYYY-MM-DD with a sibling raw_text · an ongoing role has end_date: null and is_current: true · list items carry a stable integer id. Every key is always present, so you never need existence checks.

Top-level fields

id · external_ref · file_name · status · parsed_at · personal_info · experience[] · total_experience · employment_gaps[] · education[] · skills[] · certifications[] · projects[]

Example payload

json
{
  "id": "res_9f2a4c81",
  "external_ref": "deloitte/bangalore/req-4471",
  "file_name": "cv.pdf",
  "status": "parsed",
  "parsed_at": "2026-07-24T10:45:00Z",
  "personal_info": {
    "name": "Dana Kim",
    "emails": ["dana.kim@example.com"],
    "phones": ["+1 415 555 0132"],
    "locations": ["San Francisco, CA"],
    "links": ["https://linkedin.com/in/danakim"]
  },
  "experience": [
    {
      "id": 1,
      "title": "Senior Product Designer",
      "company": "Northwind",
      "is_current": true,
      "dates": {
        "raw_text": "May 2021 – Present",
        "start_date": "2021-05-01",
        "end_date": null,
        "is_current": true,
        "months_in_position": 38,
        "duration_display": "3 yrs 2 mos"
      }
    }
  ],
  "total_experience": { "months": 96, "display": "8 yrs" },
  "employment_gaps": [],
  "education": [
    {
      "id": 1,
      "institution": "UC Berkeley",
      "degree": "B.A. Design",
      "grade": null,
      "dates": {
        "raw_text": "2012 – 2016",
        "start_date": "2012-09-01",
        "end_date": "2016-05-01"
      }
    }
  ],
  "skills": ["Figma", "React", "User Research"],
  "certifications": ["Nielsen Norman UX Certification"],
  "projects": []
}
Did this page help you?