Coding agent documentation index Fetch the complete documentation index at: https://docs.worklittle.com/docs-agent-manifest.json Use this file to discover all available pages before exploring further.

Apply for jobs

Apply to jobs from your app with one API call. Worklittle fills out and submits the employer's own application, then reports the result.

One call applies to a job. Worklittle opens the employer's application, fills every field from the person's profile and resume, answers screening questions, and submits it. You track progress with a status URL or a webhook. Scope: jobs:apply. Full reference: Apply for jobs.

| You are building | Read |
| --- | --- |
| An app or agent that applies for its own signed-in user | This page |
| A recruiting or staffing agency that applies for many candidates | [Recruiting agency](/use-cases/recruiting-agency) |
| A job board that adds an Apply button to its listings | [Apply on your job board](/use-cases/job-board-apply) |
| A careers page for one employer's own postings | [Embedded job board](/use-cases/embedded-job-board) |

Install the agent skill

Paste this into your coding agent (Claude Code, Cursor, Codex, and others):

set up worklittle.com/SKILL.md

Who you apply as

Every application is for one person. Who that person is depends on the key.

| Key | Applies as | What to send |
| --- | --- | --- |
| Personal workspace key | The key owner, from their Worklittle profile and resumes | `job_id` only |
| Company workspace key or platform key | An **applicant**: a person you apply for | `applicant` (first time) or `applicant_id` (every time after) |

An applicant does not need a Worklittle account. The first call creates them from their name, email, and resume and returns an applicant_id. That id is the person from then on. See [The applicant_id](#the-applicant-id).

Steps

1. Practice. POST /v1/apply with { "test": true } runs a free practice application. Nothing is sent to an employer. 2. Pick a job. Use an id from Search jobs (GET /jobs, MCP search_jobs). Every search result can be applied to. 3. Start. POST /v1/apply with job_id (MCP apply_for_job). The response has session_id, status_url, next_step, already_applied, and applicant_id. 4. Track. Poll status_url every 10 seconds and follow next_step (MCP check_application_status), or pass webhook_url and wait for events. 5. Finish. completed means the employer received it. Answer questions or approve when the status asks you to. See [Session states](#session-states).

curl -s -X POST "https://api.worklittle.com/v1/apply" \
  -H "Authorization: Bearer $WORKLITTLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "job_id": "4829105736" }'
{
  "session_id": "8f3c2a71-5d4e-4b9a-a6c1-2e7f90b4d3a8",
  "status_url": "https://api.worklittle.com/v1/apply/8f3c2a71-5d4e-4b9a-a6c1-2e7f90b4d3a8",
  "next_step": "In progress. Poll GET /v1/apply/8f3c2a71-5d4e-4b9a-a6c1-2e7f90b4d3a8 every 10 seconds.",
  "already_applied": false,
  "applicant_id": null
}

Up to 10 jobs for the same person in one call: send job_ids instead of job_id. SDK: wl.apply.create({ job_id }) and wl.apply.waitForApplication(id).

The applicant_id

On company and platform keys you apply for other people, so you name the person on every call.

First application: send applicant with at least name and email, plus their resume as resume_file ({ "filename", "content_base64" }, PDF or Word) or resume_text.

curl -s -X POST "https://api.worklittle.com/v1/apply" \
  -H "Authorization: Bearer $WORKLITTLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "job_id": "4829105736",
    "applicant": { "name": "Sam Lee", "email": "sam@example.com", "phone": "+1 415 555 0100", "city": "Austin", "state": "TX" },
    "resume_file": { "filename": "sam-lee.pdf", "content_base64": "JVBERi0x..." }
  }'

The response includes "applicant_id": "a1d27c94-6b3e-4f0a-9c58-7e2b1f4d6a90". Save it permanently with the person in your own database.

Every later application: send applicant_id instead of applicant. No resume upload needed.

curl -s -X POST "https://api.worklittle.com/v1/apply" \
  -H "Authorization: Bearer $WORKLITTLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "job_id": "7310582946", "applicant_id": "a1d27c94-6b3e-4f0a-9c58-7e2b1f4d6a90" }'
| Rule | What it means for you |
| --- | --- |
| One person, one applicant | One email maps to one applicant. A second create with the same email returns 409 `APPLICANT_EXISTS`, and Worklittle emails the id to that address. |
| Never re-create for a change | New phone, city, or resume: `POST /v1/apply/profile` with `"action": "save"`, the `applicant_id`, and only what changed. |
| The id travels with the person | Worklittle emails the id to the applicant. Any API key it is given can apply for them. Each application bills the key that started it. |
| Only the creator deletes | Only the key that created the applicant can delete it or turn its auto-apply on or off. |

Read one person's profile, applications, and employer emails with POST /v1/apply/profile and { "action": "get", "applicant_id": "..." }. Lists on shared keys need ?applicant_id=.

On a personal key, job_id alone applies as you. To apply for someone else from a personal key, add "use_profile": false with applicant or applicant_id.

Session states

| `session.status` | What to do |
| --- | --- |
| `queued`, `running` | Keep polling |
| `awaiting_input` | Read `questions`, ask the person, then `POST /v1/apply/{id}` with `{ "action": "continue", "answers": { ... } }` |
| `paused` | Follow `next_step` |
| `awaiting_submit` | Show `final_fields`, then `POST /v1/apply/{id}` with `{ "action": "approve_submit" }` (MCP `submit_application`) |
| `completed` | Submitted. Only this status means the employer received it |
| `failed`, `stopped` | Show `stop_message` to the person. Check `GET /v1/applications` before retrying |

Submits by default. Send auto_submit: false to hold every application at awaiting_submit for review. Change what it fills mid-run with { "action": "steer", "instructions": "..." }; end it with { "action": "stop" }.

Cost

$0.20 per application, or $0.05 on a personal key with Worklittle Instant. Company workspace and platform keys pay $0.20. Charged once per person per job, when the application is submitted or stops at your call. Free when it fails on Worklittle's side, when already_applied is true, and for test: true. See Pricing.

Gotchas

Only Worklittle job ids. job_id is the numeric id from search, not an employer URL. A job that closed returns 410 JOB_CLOSED with apply_url, at no cost. Very rarely the employer's site blocks the application (for example a captcha); it then ends failed with the reason in error_message, free. See Closed jobs. Duplicates. Applying twice to the same job for the same person returns already_applied: true and is free. An Idempotency-Key header makes a retried start safe. Company limit. Past max_per_company applications at one company in 30 days (default 3, up to 10), the start returns 409 COMPANY_LIMIT_REACHED. Ask the person, then resend with a higher max_per_company. 402 PAYMENT_REQUIRED. Credit does not cover the price and no card is on file. Do not retry in a loop. 429. APPLY_LIMIT_REACHED is a daily or monthly cap; APPLICANT_PAUSED means one applicant failed 15+ times in 24 hours. See Rate limits. Webhooks. webhook_url receives signed apply.session.<status> and apply.outcome.* events. Verify Worklittle-Webhook-Signature with the secret from GET /v1/apply-webhook-secret.

Tracking

GET /v1/applications (MCP list_applications) lists every application with status, outcome (interview, offer, rejected, or null) and cost_usd. Add status=pending for unfinished ones and applicant_id on shared keys. Free.

On a personal key, the job tracker also covers applications made elsewhere: GET /jobs/applied, POST /jobs/applied to record one, and PATCH /jobs/applied/:job_id to change its stage.