Career Site Auto Apply avatar

Career Site Auto Apply

Under maintenance

Pricing

from $100.00 / 1,000 application createds

Go to Apify Store
Career Site Auto Apply

Career Site Auto Apply

Under maintenance

Apply 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

Jobo

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

5 days ago

Last modified

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 Entity
Content-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; or
  • job_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:

ValueWhat to do
retry_startRepeat the exact start body and Idempotency-Key.
submit_answersAnswer the latest application.current_step using the latest session token.
retry_answersRepeat the exact answers body and the same session token.
completeStop. 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 typeValue
text, textarea, select, radiostring; select/radio must use an advertised option value
multi_selectarray of advertised option values
checkboxboolean
numbernumber
dateYYYY-MM-DD string
partial_dateYYYY, YYYY-MM, or YYYY-MM-DD
typeahead{"query":"…","selection":{"value":"…","label":"…"}}
file{"url":"https://…","filename":"resume.pdf","content_type":"application/pdf"}
repeating_grouparray 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

HTTPTypical codeMeaning
400invalid_request, validation_failedFix the request shape or field answers before retrying.
401invalid_sessionThe Jobo session is expired, altered, or belongs to another Apify user.
402spending_limit_reachedIncrease the Apify run spending limit, then retry the start safely.
409idempotency_key_reuse, stale_correction_roundUse the original target or refresh the current step and round.
422unsupported_atsThe target is not a supported public Ashby job URL; no charge is made.
429rate_limit_exceededWait for Retry-After, then replay exactly.
502upstream_unavailableJobo could not be reached; replay safely.
503billing_pending, provider_catalog_unavailableWait for Retry-After when present, then replay exactly.
504upstream_timeoutReplay 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.

LinkUse it for
Jobo service statusLive availability and incident updates for the Jobo API behind this Actor
Ashby Jobs ScraperFind and filter live Ashby jobs before sending a supported application URL
ATS Jobs APISearch jobs across 150+ ATS platforms; filter to source ashby for targets supported by this release
AI Deep Job SearchDiscover and score matching jobs before beginning an application
All Jobo ActorsBrowse the complete Jobo catalogue on Apify