curl on localhost can drive an entire application.
1. Create blocks until the fields arrive
POST /api/auto-apply/applications holds the connection while Jobo validates
the target, acquires a browser, opens the form, and extracts its fields —
typically 10 seconds to 3 minutes. The response is the application with
status: "awaiting_answers" and the fields to answer in current_step:
status: "failed" with a
failure code.
Keep your HTTP client timeout above 540 seconds: the server holds a
blocking call for up to ~9 minutes before answering 202 with a snapshot
(see Recovery for what to do then).
2. Answers are validated synchronously — mistakes are free
POST /api/auto-apply/applications/{id}/answers takes the complete answer
snapshot for the current step:
400 validation_failed immediately, with
per-field detail in errors:
correction_round in the request is an optional guard: when present
and stale, the API refuses with 409 stale_correction_round rather than
answering the wrong round.)
Once the answers are accepted, Jobo fills the page and advances the form —
intermediate pages auto-continue, the final page auto-submits; the
browser agent decides which from the page itself. The call then blocks until
one of three outcomes:
3. Correction rounds
Client-side validation cannot predict everything the employer’s ATS enforces. When the ATS rejects a value after filling, the same step comes back withcorrection_round incremented and command_errors describing what was
rejected:
correction_limit_exceeded.
4. Deadlines
While a step is awaiting answers, a real browser is holding the employer’s form open. Each answerable step carriesanswers_expire_at — about 3
minutes, capped at 60 seconds for one-time verification-code steps.
Past the deadline the application fails with answers_timeout
(verification_timeout for code steps). Answer promptly; if your answer
source is slow, compute answers before creating the application.
5. Recovery
Every blocking call can lose its connection — a deploy, a proxy timeout, a crashed process. Recovery is built into the contract:- Create dropped? Repeat the same
POSTwith the sameIdempotency-Key. The replay re-attaches to the in-flight application and resumes blocking on the same wait. (A different body with a reused key is409 idempotency_key_reuse.) - Answers dropped? Repeat the same
POST. Answers are accepted exactly once per (step, correction round); a duplicate post attaches to the in-flight wait and its payload is ignored. - Got a
202? The server’s hold budget (~9 minutes) expired while the application was still working. The body is a snapshot; continue withGET /api/auto-apply/applications/{id}?wait_seconds=540, which long-polls until the application is answerable or terminal.
6. Local development
Run your integration anywhere — localhost, CI, a notebook. Nothing about the loop requires inbound connectivity. The one exception:file field answers (resumes) are supplied as a public
HTTPS URL that Jobo downloads. Host the file anywhere Jobo can reach — object
storage with a signed URL works well. A localhost URL is rejected with
unsafe_file_url.
7. Cancel
POST /api/auto-apply/applications/{id}/cancel requests cancellation at any
point. Queued applications cancel immediately; executing ones stop at the next
safe checkpoint. A submission the ATS already confirmed wins the race — the
application ends submitted, with cancel_requested: true recording the
attempt.
