Career Site Auto Apply
Under maintenancePricing
from $100.00 / 1,000 application createds
Career Site Auto Apply
Under maintenanceApply to public Ashby jobs through a secure start-and-answer API. Receive employer questions, submit complete answers, and pay once per accepted attempt.
Pricing
from $100.00 / 1,000 application createds
Rating
0.0
(0)
Developer
Jobo
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
5 days ago
Last modified
Categories
Share
Apply to public Ashby jobs through a two-endpoint API:
start → questions → answers → next questions or final result
The Actor runs continuously in Apify Standby mode. Jobo owns the browser session and outbound proxy; the Actor authenticates the Apify caller, protects application sessions, and charges once for an accepted application attempt. You can start through the Actor input form or the HTTP API. Answer rounds always continue through the Standby API; no dataset is written.
This API submits real job applications. Once all required answer steps are accepted, Jobo submits the form to the employer automatically. Test only with vacancies that are explicitly identified as sandboxes or test postings.
Supported jobs: Ashby only
This release supports public jobs hosted on jobs.ashbyhq.com. Use either of these URL shapes:
https://jobs.ashbyhq.com/{organization-slug}/{job-uuid}https://jobs.ashbyhq.com/{organization-slug}/{job-uuid}/application
Example:
https://jobs.ashbyhq.com/brighthire-sandbox/271829e3-b51f-4304-8e04-c7627d807707/application
The organization slug may contain letters, numbers, hyphens, underscores, and interior dots. It must start alphanumerically and cannot end with a dot or contain consecutive dots. The job ID must be a UUID. A trailing slash, query string, or fragment is allowed.
The following are not supported:
- Ashby board homepages without a job UUID;
- application-request, survey, assignment, event, or authenticated Ashby URLs;
- embedded or custom-domain Ashby career sites; and
- Greenhouse, Lever, Workday, or any other non-Ashby ATS.
You may send a Jobo job_id instead of an apply_url, but that job must resolve to a supported Ashby URL. Otherwise the Actor cancels the upstream attempt before billing.
A valid HTTPS URL outside this scope returns the following response and is not charged:
HTTP/1.1 422 Unprocessable EntityContent-Type: application/problem+json
{"type": "https://apify.com/jobo.world/career-site-auto-apply/errors/unsupported_ats","title": "Unsupported ATS","status": 422,"detail": "This Actor currently supports only public Ashby job URLs in the documented jobs.ashbyhq.com format.","code": "unsupported_ats","api_version": "v1"}
Price
application-created costs $0.10 once per accepted application attempt. Platform usage is included; there is no compute, proxy, or per-step charge.
- Malformed requests, unsupported targets, and starts rejected before Jobo creates an application are free.
- Replays and concurrent starts produce at most one charge.
- An accepted attempt remains billable if the employer's ATS later rejects or fails it.
- If the Apify spending limit prevents charging, the Actor cancels the new application and returns
402 spending_limit_reached.
Quick start
Call the authenticated Standby URL using your Apify API token. Keep the token, idempotency key, and returned Jobo session token private.
Optional: start from the Actor input form
In Apify Console, enter the Ashby apply_url and run the Actor. The run makes the same initial application call and writes the response to the default key-value store as OUTPUT. It includes the first questions (or terminal result), a session_token, next_action, and the effective idempotency_key.
The input form handles only the initial call. Use POST /v1/applications/answers below for every answer round. If the run returns next_action: retry_start, repeat POST /v1/applications with the returned idempotency_key and the same URL. Supplying your own optional idempotency_key makes re-attaching across Actor runs straightforward.
1. Start or re-attach
curl --request POST \"https://jobo-world--career-site-auto-apply.apify.actor/v1/applications" \--header "Authorization: Bearer $APIFY_TOKEN" \--header "Content-Type: application/json" \--header "Idempotency-Key: candidate-42-brighthire-test" \--data '{"apply_url":"https://jobs.ashbyhq.com/brighthire-sandbox/271829e3-b51f-4304-8e04-c7627d807707/application"}'
Send exactly one target:
apply_url: a supported public Ashby job URL; orjob_id: a Jobo job UUID whose application URL is supported by this Actor.
A successful answerable response resembles this abridged example:
{"session_token": "jobo1.…","session_expires_at": "2026-08-31T04:00:00.000Z","next_action": "submit_answers","application": {"api_version": "2026-08-31","id": "11111111-1111-4111-8111-111111111111","provider_id": "ashby","status": "awaiting_answers","current_step": {"id": "22222222-2222-4222-8222-222222222222","correction_round": 0,"answers_expire_at": "2026-08-30T04:10:00.000Z","fields": [{"field_id": "_systemfield_name","label": "Name","type": "text","requires_answer": true},{"field_id": "_systemfield_resume","label": "Resume","type": "file","requires_answer": true}]}}}
If the response is 202 with next_action: retry_start, repeat the same body and Idempotency-Key. Two Apify users cannot collide because the Actor namespaces the upstream key to the authenticated user. Reusing one key for a different target returns 409 idempotency_key_reuse.
2. Submit a complete answer snapshot
Answer every field in application.current_step whose requires_answer is true. Use the latest session token and echo the step's correction_round.
curl --request POST \"https://jobo-world--career-site-auto-apply.apify.actor/v1/applications/answers" \--header "Authorization: Bearer $APIFY_TOKEN" \--header "Content-Type: application/json" \--header "X-Jobo-Session: $JOBO_SESSION" \--data '{"correction_round": 0,"answers": [{"field_id":"_systemfield_name","value":"Ada Lovelace"},{"field_id":"_systemfield_resume","value":{"url":"https://files.example.com/temporary/resume.pdf?signature=…","filename":"resume.pdf","content_type":"application/pdf"}}]}'
Before writing, the Actor refreshes the current Jobo state. If the token's step or correction round was already processed, it returns the refreshed application and a rotated token without applying the snapshot twice.
Follow next_action until it says complete:
| Value | What to do |
|---|---|
retry_start | Repeat the exact start body and Idempotency-Key. |
submit_answers | Answer the latest application.current_step using the latest session token. |
retry_answers | Repeat the exact answers body and the same session token. |
complete | Stop. Inspect application.status and application.failure. |
Terminal statuses are submitted, failed, and canceled. A 202 answer response, connection loss, or client timeout is not proof of failure: replay the same token and complete body to re-attach safely.
JavaScript loop
This complete control-flow helper leaves only field answering to your application:
const ACTOR_URL = "https://jobo-world--career-site-auto-apply.apify.actor";const sleep = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));export async function applyToAshby({ apifyToken, applyUrl, idempotencyKey, answerStep }) {const call = async (path, headers, body) => {const response = await fetch(`${ACTOR_URL}${path}`, {method: "POST",headers: {Authorization: `Bearer ${apifyToken}`,"Content-Type": "application/json",...headers,},body: JSON.stringify(body),});const payload = await response.json();if (response.status !== 200 && response.status !== 202) {const error = new Error(payload.detail ?? `Request failed with ${response.status}`);error.status = response.status;error.problem = payload;throw error;}const retryAfterSeconds = Number(response.headers.get("Retry-After") ?? "1");return {payload,retryAfterMs: Number.isFinite(retryAfterSeconds)? Math.max(1, retryAfterSeconds) * 1000: 1000,};};let result;let reply;do {reply = await call("/v1/applications",{ "Idempotency-Key": idempotencyKey },{ apply_url: applyUrl },);result = reply.payload;if (result.next_action === "retry_start") await sleep(reply.retryAfterMs);} while (result.next_action === "retry_start");while (result.next_action === "submit_answers") {const step = result.application.current_step;const body = {correction_round: step.correction_round,answers: await answerStep(step.fields.filter((field) => field.requires_answer)),};const session = result.session_token;do {reply = await call("/v1/applications/answers",{ "X-Jobo-Session": session },body,);result = reply.payload;if (result.next_action === "retry_answers") await sleep(reply.retryAfterMs);} while (result.next_action === "retry_answers");}return result.application;}
answerStep(fields) must return a complete [{ field_id, value }] array for the supplied fields. Production clients should also add bounded retry handling for 429, 502, 503, and 504; respect Retry-After when present.
Answer value shapes
Use the value shape matching each field's type:
| Field type | Value |
|---|---|
text, textarea, select, radio | string; select/radio must use an advertised option value |
multi_select | array of advertised option values |
checkbox | boolean |
number | number |
date | YYYY-MM-DD string |
partial_date | YYYY, YYYY-MM, or YYYY-MM-DD |
typeahead | {"query":"…","selection":{"value":"…","label":"…"}} |
file | {"url":"https://…","filename":"resume.pdf","content_type":"application/pdf"} |
repeating_group | array of objects keyed by the advertised item_fields[].key |
For file answers, url must be a public or temporary signed HTTPS URL that remains downloadable by Jobo while the step is processed. The Actor has no upload endpoint. Local paths, data URLs, and URLs requiring custom request headers do not work.
Submit fields whose requires_answer is true even when the correct value is false, zero, or an allowed empty collection. Synchronous field problems return 400 validation_failed; they are free and do not consume a correction round.
Correction rounds and deadlines
Ashby can reject a value after browser submission. Jobo then returns the step with a higher correction_round and command_errors. Build a corrected, complete snapshot from the new current_step, use the new token, and echo the new round. A stale round returns 409 stale_correction_round.
Every answerable step includes answers_expire_at. Missing it produces a terminal failure such as answers_timeout or verification_timeout. Session access expires 24 hours after application creation and is not extended by later calls.
Errors and retries
| HTTP | Typical code | Meaning |
|---|---|---|
400 | invalid_request, validation_failed | Fix the request shape or field answers before retrying. |
401 | invalid_session | The Jobo session is expired, altered, or belongs to another Apify user. |
402 | spending_limit_reached | Increase the Apify run spending limit, then retry the start safely. |
409 | idempotency_key_reuse, stale_correction_round | Use the original target or refresh the current step and round. |
422 | unsupported_ats | The target is not a supported public Ashby job URL; no charge is made. |
429 | rate_limit_exceeded | Wait for Retry-After, then replay exactly. |
502 | upstream_unavailable | Jobo could not be reached; replay safely. |
503 | billing_pending, provider_catalog_unavailable | Wait for Retry-After when present, then replay exactly. |
504 | upstream_timeout | Replay the same key or session token and body to re-attach. |
Jobo problem bodies and stable codes are forwarded faithfully. Do not blindly retry other 4xx responses.
Privacy and permissions
Responses contain the full versioned application: fields, accepted answers, correction errors, deadlines, and terminal failure. The shared Jobo service account's owner_id is always removed.
The Actor uses limited Apify permissions and a named Request Queue only as its billing ledger. It does not use Apify Proxy. API keys, answer bodies, file URLs, full application URLs, and session tokens are never logged. Operational logs contain only hashed user/session identifiers, route, latency, status, and stable error code.
The Actor's source files are hidden from the public Apify listing. The README, input/output schemas, OpenAPI definition, and non-sensitive build metadata remain public so callers can evaluate and integrate the API. The dedicated Jobo API key and publisher signing secret are stored as encrypted Apify secrets; their values are not included in public Actor, version, or build metadata.
OpenAPI
The Standby API definition is published from .actor/web_server_openapi.json. The internal GET / readiness probe required by Apify Standby is intentionally excluded from the public paths.
Related links
| Link | Use it for |
|---|---|
| Jobo service status | Live availability and incident updates for the Jobo API behind this Actor |
| Ashby Jobs Scraper | Find and filter live Ashby jobs before sending a supported application URL |
| ATS Jobs API | Search jobs across 150+ ATS platforms; filter to source ashby for targets supported by this release |
| AI Deep Job Search | Discover and score matching jobs before beginning an application |
| All Jobo Actors | Browse the complete Jobo catalogue on Apify |