API Reference
Send a resume, receive structured JSON. One schema, one integration.
https://api.resumeparsing.ai/v1Introduction
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:
{ "success": true, "data": { ... } }Error:
{
"success": false,
"error": { "code": "invalid_api_key", "message": "..." }
}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.
Authorization: Bearer rp_live_1a2b3c4d5e6f7a8b:9f3c...<48 hex secret>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.
Errors
Errors use standard HTTP status codes and a stable machine-readable code in the error envelope.
| HTTP | Code | When |
|---|---|---|
| 400 | invalid_request | Missing or malformed parameter. |
| 401 | invalid_api_key | Key missing, malformed, unknown, revoked, or workspace suspended. All identical. |
| 402 | insufficient_credits | Workspace credit balance is zero or below. |
| 404 | not_found | Unknown id, or an id owned by another workspace (never 403). |
| 413 | batch_too_large | More than 200 files or over 500 MB in one batch. |
| 422 | unreadable_file | Empty, oversized, or not a recognised resume format. |
| 429 | rate_limited | Over the workspace rate limit. Carries a Retry-After header. |
| 5xx | internal_error | Unexpected. Generic message that never leaks internals. |
Submit a resume
/v1/resumesUpload 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.
| Field | Type | Description |
|---|---|---|
file | file | PDF, DOC, DOCX, TXT or HTML. Up to 10 MB. |
external_ref | string | Up 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_time | ISO 8601 | Must be in the future. Defaults to now + 30 days retention. |
Required
Example request
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
{
"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
}
}Retrieve a resume
/v1/resumes/:idFetch 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.
curl https://api.resumeparsing.ai/v1/resumes/res_9f2a4c81 \
-H "Authorization: Bearer rp_live_1a2b3c4d5e6f7a8b:<secret>"Delete a resume
/v1/resumes/:idPermanently 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.
Batches
/v1/batchesComing soon/v1/batches/:idComing soon/v1/batches/:id/resultsComing soonSubmit up to 200 resumes (500 MB) in one request and track them together. A batch.completed webhook fires when the whole batch finishes.
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.
{
"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"
}
}Resume lifecycle
A resume moves through four public statuses. The internal pipeline stages are never exposed.
Accepted and waiting to be processed.
Text is being extracted and fields parsed.
Done. The data payload is available.
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.
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
{
"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": []
}