Job application form template that screens as it collects

Build & score

Short answer: this is a complete QuizGen form definition for a job application — name, contact, an uploaded resume, a portfolio link, a few screening questions, and a scoring block that sorts applicants into "screen now," "review," or "not a fit" as they submit. POST it as-is, or hand it to an AI assistant to adapt for your role.

Resume uploads need an account

Candidates can attach a resume directly: the file_upload question type takes PDFs and Word documents, and the file lands in your account rather than in a share link that may or may not still work in three weeks.

The one catch: file_upload needs a (free) account — in the sandbox, creating a form that contains one returns 402 plan_limit. Limits differ by plan: Free and Ad-free allow 10 MB per file and 100 MB of storage in total, Plus 25 MB per file and 10 GB.

If you're trying it in the sandbox, delete the resume_file question from the template below and keep portfolio_link — a url question asking for a Drive link, personal site, LinkedIn, or GitHub. That's a genuinely fine substitute for engineering, design, and writing roles, where a live portfolio often tells you more than a PDF. It's a worse substitute when you need a formatted document to pass along to someone else.

The template below asks for both, which is usually the right call: the file for your records, the link for the work itself.

One thing worth knowing if an assistant is building this for you: the answer to a file_upload question is an array of file ids that the server issues while the candidate uploads. You never write that value into a definition, and there is no API for attaching a file on someone's behalf — uploads only happen through the hosted form.

The template

{
  "schema_version": 1,
  "kind": "form",
  "title": "Apply: Product Designer",
  "description": "Takes about 5 minutes. We read every application.",
  "settings": {
    "collect_respondent": "email_required"
  },
  "sections": [
    {
      "key": "candidate",
      "title": "About you",
      "questions": [
        { "id": "full_name", "type": "short_text", "prompt": "Full name",
          "required": true, "placeholder": "Jordan Smith" },
        { "id": "email", "type": "email", "prompt": "Email address",
          "required": true, "placeholder": "you@example.com" },
        { "id": "phone", "type": "phone", "prompt": "Phone number",
          "required": true, "placeholder": "+1 555 555 5555" },
        { "id": "resume_file", "type": "file_upload", "prompt": "Upload your resume",
          "help": "PDF or Word document.",
          "required": true, "max_files": 1, "accept": ["pdf", "document"] },
        { "id": "portfolio_link", "type": "url", "prompt": "Link to a portfolio, LinkedIn, or GitHub",
          "help": "Optional, but it usually helps more than the resume does.",
          "placeholder": "https://" }
      ]
    },
    {
      "key": "role",
      "title": "The role",
      "questions": [
        { "id": "position", "type": "choice", "prompt": "Which role are you applying for?",
          "required": true,
          "options": [
            { "value": "product_designer", "label": "Product Designer" },
            { "value": "senior_product_designer", "label": "Senior Product Designer" },
            { "value": "design_intern", "label": "Design Intern" }
          ] },
        { "id": "years_experience", "type": "number",
          "prompt": "Years of relevant experience", "required": true,
          "min": 0, "unit": "years" },
        { "id": "authorization", "type": "choice",
          "prompt": "Work authorization and location", "required": true,
          "options": [
            { "value": "us_remote", "label": "Authorized to work in the US, remote" },
            { "value": "us_onsite", "label": "Authorized to work in the US, near our office" },
            { "value": "sponsorship_needed", "label": "Would need visa sponsorship" },
            { "value": "outside_us", "label": "Based outside the US" }
          ] },
        { "id": "key_skills", "type": "multi_choice",
          "prompt": "Which of these do you have hands-on experience with?",
          "min": 1,
          "options": [
            { "value": "figma", "label": "Figma" },
            { "value": "design_systems", "label": "Design systems" },
            { "value": "user_research", "label": "User research" },
            { "value": "html_css", "label": "HTML/CSS" },
            { "value": "prototyping", "label": "Prototyping (motion/interaction)" }
          ] },
        { "id": "why_role", "type": "long_text",
          "prompt": "Why this role, and why us?", "rows": 5, "required": true,
          "examples": [
            "I've used your product for two years and want to fix the onboarding flow I struggled with"
          ] }
      ]
    },
    {
      "key": "consent",
      "title": "Before you submit",
      "questions": [
        { "id": "data_consent", "type": "consent",
          "prompt": "I consent to this application, including my contact details and answers, being stored and reviewed by the hiring team for this role.",
          "required": true }
      ]
    }
  ],
  "outcomes": {
    "method": "points",
    "points": {
      "authorization": { "us_remote": 3, "us_onsite": 3, "sponsorship_needed": 1, "outside_us": 0 },
      "key_skills": { "figma": 1, "design_systems": 2, "user_research": 1, "html_css": 1, "prototyping": 1 }
    },
    "buckets": [
      { "key": "not_a_fit", "max": 2, "title": "Thanks for applying",
        "body": "We'll keep your application on file and reach out if a better-matched role opens up." },
      { "key": "review", "min": 3, "max": 5, "title": "Application received",
        "body": "Your application is in the queue for review — we'll follow up within two weeks either way." },
      { "key": "screen_now", "min": 6, "title": "Thanks — you're a strong match on paper",
        "body": "We'll reach out to schedule a first call within the next few days." }
    ]
  }
}

Note on years_experience: outcomes.points scores option values, which only exist on choice-shaped questions — a plain number field can't be scored directly. years_experience is collected here for display and manual review, not scoring. If you want years of experience to feed the score (e.g. 0–1 years = 0 points, 2–4 years = 2, 5+ years = 4), convert it to a choice question with those bands as options and score each option in outcomes.points the same way authorization is scored below.

What each piece is doing

  • resume_file is a file_upload limited to ["pdf", "document"] with max_files: 1 — resumes only, so you don't get a folder of screenshots. Needs an account; drop this question in the sandbox.
  • portfolio_link is a url, deliberately optional. Asking for both a file and a link costs the candidate nothing and covers both the "send this to the hiring manager" case and the "actually look at their work" case.
  • authorization as a choice (not free text) means you can score it and filter responses by it later — much easier than parsing sentences.
  • key_skills is multi_choice with min: 1; each selected skill adds its own points in outcomes.points, so someone who checks three relevant skills scores higher than someone who checks one.
  • data_consent is a required consent question — a timestamped record that the candidate agreed to have their application stored and reviewed, which is worth having regardless of your local privacy-law requirements.
  • outcomes with points/buckets is the differentiator here: instead of just collecting applications, QuizGen scores each one as it comes in and stores score and outcome on the response, so you can sort your dashboard by "screen_now" first instead of reading 200 applications in submission order.

This is a triage aid, not a hiring decision

Say this plainly to whoever's using it: automated scoring should narrow the queue, not make the call. A few rules worth following:

  • Score only job-relevant criteria — years of experience, required authorization, named skills. Never score name, address, alma mater, or anything that correlates with a protected characteristic.
  • Keep a human reviewing every bucket, including "not_a_fit" — automated screening is good at surfacing the strong matches faster, bad at being the final word on a candidate.
  • Check your local rules. Some jurisdictions (New York City's Local Law 144 is the well-known example) regulate automated employment decision tools specifically — know whether yours applies before you rely on scoring for more than internal triage.

The same outcomes mechanism — points per answer, buckets with a title/body — is exactly what powers lead qualification forms and general quizzes with scoring; if you haven't used outcomes before, either of those is a good second read.

Route new applications into Slack or your ATS

Don't make anyone babysit a dashboard. Set a webhook on the quiz and every completed application POSTs to your endpoint immediately, with the answers, score, and outcome bucket included — pipe it into a Slack channel, or into whatever ATS or spreadsheet already runs your hiring pipeline.

Let an AI assistant fill it in

Connect QuizGen's MCP server and say something like:

Read https://quizgen.dev/blog/job-application-form-template.md and build me an application form for a "Backend Engineer" role — require 3+ years of experience, score Python and Postgres skills highest, and require US work authorization to land in the screen_now bucket. Give me the link.

FAQ

Can candidates actually attach a PDF resume? Yes, on any account — that's the file_upload question. In the sandbox it returns 402 plan_limit, so drop the question and rely on the link.

How big a file can they send? 10 MB per file on Free and Ad-free, 25 MB on Plus, against 100 MB and 10 GB of account storage respectively. A resume will never come close; a reel or a design portfolio might.

Can I accept a cover letter too? Raise max_files (up to 5) on the same question, or add a second file_upload for cover letters specifically. Keep accept narrow either way.

Can I require the resume but not phone? Yes — toggle required per question independently; nothing forces you to require every field.

Does the scoring reject anyone automatically? No. outcomes only sets a score and outcome bucket on the stored response and (optionally) a different completion message — it never blocks submission or hides an application from you.

Can I add more screening questions later? Yes — PUT a revised definition; existing responses keep the definition_version they answered under, so past applications aren't retroactively rescored.

What if I don't want scoring at all? Drop the outcomes block entirely — the rest of the form works fine as a plain application collector.


Full schema, question types, and endpoints: quizgen.dev/llms.txt.

$ curl quizgen.dev/blog/job-application-form-template.md

This guide as raw markdown — no HTML for your agent to parse.

View .md

Keep reading