Last updated: January 6

<span aria-hidden="true" id="lets-build-ai-resume-parser-with-transloadit"></span>

# Let's Build: AI resume parser with Transloadit

![Kevin van Zonneveld](/assets/images/teammates/avatar-kvz-4.jpg?dpl=dpl_AsMTCxwVXNuJ5TmdPevSCe63JuJo)

**Kevin van Zonneveld**

Co-founder · Amsterdam, The Netherlands · Show bio

[](https://x.com/kvz)[](https://github.com/kvz)

Resume parsing is a classic SaaS problem: take messy, real-world documents and extract structured fields that feed ATS pipelines. With Transloadit, you can build that workflow from primitives in a single assembly.

<span aria-hidden="true" id="what-were-building"></span>

## What we’re building

* Accept PDF, DOCX, or image resumes
* Convert non-PDFs to PDF with [🤖 /document/convert](/docs/robots/document-convert.md)
* Extract fields with [🤖 /ai/chat](/docs/robots/ai-chat.md)

<span aria-hidden="true" id="schema-first-zod"></span>

## Schema first (zod)

```ts
import { z } from 'zod'
import { zodToJsonSchema } from 'zod-to-json-schema'

const resumeSchema = z.object({
  full_name: z.string().optional(),
  headline: z.string().optional(),
  email: z.string().optional(),
  phone: z.string().optional(),
  location: z.string().optional(),
  summary: z.string().optional(),
  skills: z.array(z.string()).optional(),
  work_experience: z
    .array(
      z.object({
        company: z.string().optional(),
        title: z.string().optional(),
        start_date: z.string().optional(),
        end_date: z.string().optional(),
        highlights: z.array(z.string()).optional(),
      }),
    )
    .optional(),
  education: z
    .array(
      z.object({
        institution: z.string().optional(),
        degree: z.string().optional(),
        start_date: z.string().optional(),
        end_date: z.string().optional(),
      }),
    )
    .optional(),
})

const toJsonSchema = (schema: z.ZodTypeAny): unknown =>
  typeof (z as { toJSONSchema?: typeof zodToJsonSchema }).toJSONSchema === 'function'
    ? (z as { toJSONSchema: typeof zodToJsonSchema }).toJSONSchema(schema)
    : zodToJsonSchema(schema)

const resumeJsonSchema = toJsonSchema(resumeSchema)

```

<span aria-hidden="true" id="pipeline-overview"></span>

## Pipeline overview

```
PDF resumes ──▶ /ai/chat
Other docs  ──▶ /document/convert (pdf) ──▶ /ai/chat

```

<span aria-hidden="true" id="assembly-snippet"></span>

## Assembly snippet

```ts
const assembly = await transloadit.createAssembly({
  params: {
    steps: {
      pdf_verified: {
        robot: '/file/filter',
        use: ':original',
        accepts: [['${file.mime}', '==', 'application/pdf']],
      },
      non_pdf: {
        robot: '/file/filter',
        use: ':original',
        accepts: [['${file.mime}', '!=', 'application/pdf']],
      },
      pdf_converted: {
        robot: '/document/convert',
        use: 'non_pdf',
        format: 'pdf',
      },
      extract_resume: {
        robot: '/ai/chat',
        use: ['pdf_verified', 'pdf_converted'],
        model: 'anthropic/claude-4-sonnet-20250514',
        format: 'json',
        schema: JSON.stringify(resumeJsonSchema),
        messages: 'Extract resume fields. Omit keys if unknown.',
        result: true,
      },
    },
  },
  files: {
    document: filePath,
  },
  waitForCompletion: true,
})

```

<span aria-hidden="true" id="try-the-example-app"></span>

## Try the example app

The runnable version of this post lives at `example_apps/resume-parser/run.ts`.

```bash
node example_apps/resume-parser/run.ts

```

<span aria-hidden="true" id="suggested-inputs-for-visuals"></span>

## Suggested inputs for visuals

Use the bundled samples or swap in a real resume PDF:

* `_assets/demos/inputs/first_document.pdf`
* `_assets/demos/inputs/second_document.pdf`
* `_assets/demos/inputs/scan.pdf`

<span aria-hidden="true" id="next-steps"></span>

## Next steps

* Add a normalization layer for phone numbers and dates.
* Flag missing fields and route to manual review.
* Store results in a talent database or ATS.

[#letsbuild](/blog/tags/letsbuild.md)[#ai](/blog/tags/ai.md)[#document-processing-service](/blog/tags/document-processing-service.md)[#artificial-intelligence-service](/blog/tags/artificial-intelligence-service.md)[#developer-experience](/blog/tags/developer-experience.md)

### 👩‍💻 Join 20k+ developers

Sign up for our [monthly newsletter](/newsletters.md) to receive direct links to 3 exclusive tech — and 2 product updates. No less, no more.

Your email:

Get access

## File uploading and encoding. Made simple.

Transloadit streamlines file handling for developers, trusted by brands like Coursera and The New York Times. We’re known for a reliable API, top-notch support, and a strong commitment to open source, with projects like [Uppy⁠](https://uppy.io) and [Tus⁠](https://tus.io) setting standards in file processing.

[Sign up](/c/)[Book a Demo](https://survey.typeform.com/to/kRg47Xi5)

No credit card needed

Cancel anytime
