Skip to content
Quickstart · API v1

From API key to application.

This guide takes the shortest honest route through setup: create a key, save the candidate, upload a resume, fund the account, select a job, and queue an employer application.

The endpoint referenceis generated from the API's OpenAPI document. This page is handwritten for the decisions and sequencing a schema cannot explain.

Before you start

The model in sixty seconds

All /v1 requests use a Bearer API key. Developer API v1 is U.S.-only: catalog results are U.S. jobs and candidate facts are normalized for U.S. applications. A candidate profile and resume belong to the developer account, so you configure them once and reuse them. Applications are asynchronous resources with an explicit status.

search
0.05 / 25

Per requested block of up to 25 results

managed
2 credits

Apply Guy resolves open-ended answers

agent
1 credit

Your model resolves answer rounds

rate
20 / $1

One credit is five cents

Stripe's hosted checkout requires human payment approval. Workday has one additional human prerequisite: creating a Gmail app password in Google Account settings. After that, account creation, API-key creation, profile setup, inbox verification, job discovery, submission, answer rounds, cancellation, and status delivery are programmable.

Step 1

Create the account and store its API key

The bootstrap endpoint creates a zero-balance developer account and a full-scope API key in one call. It is deliberately outside /v1, because you do not have a key yet.

bootstrap.sh
curl https://api.applyguy.ai/developer/bootstrap \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "email": "builder@example.com",
    "password": "use-a-long-unique-password",
    "name": "Production agent"
  }'
response.json
{
  "apiKey": {
    "key": "ag_live_...",
    "scopes": [
      "jobs:read", "credits:spend", "profile:read", "profile:write",
      "applications:read", "applications:write",
      "credits:read", "credits:write", "webhooks:write",
      "usage:read", "usage:share"
    ]
  },
  "refreshToken": "store-this-too-...",
  "credits": 0,
  "warning": "Store the API key and refresh token now. Neither can be retrieved again."
}
Store the ag_live_… value immediately. Only its hash is retained, so the secret cannot be read back later. Existing signed-in users can create additional scoped keys from the developer dashboard.

The response also includes a short-lived account accessToken and a one-time refreshToken for API-key and integration management. Rotate it through POST /auth/refresh and atomically replace the old refresh token with the returned one. Do not use account tokens for /v1 calls.

Step 2

Save the candidate facts, then upload the resume

Applications need at least first name, last name, email, phone, location, and a resume. Richer context produces safer deterministic mappings and better managed answers. Send facts the candidate has reviewed; do not infer legal or demographic answers casually.

profile.sh
curl https://api.applyguy.ai/v1/profile \
  -X PUT \
  -H "Authorization: Bearer $APPLYGUY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "candidateContext": {
      "firstName": "Jordan",
      "lastName": "Lee",
      "email": "jordan@example.com",
      "phone": "+14155550123",
      "location": "San Francisco, CA",
      "linkedin": "https://www.linkedin.com/in/jordan-lee",
      "address": {
        "line1": "123 Market Street",
        "city": "San Francisco",
        "state": "California",
        "postalCode": "94105",
        "country": "United States of America"
      },
      "workAuthorization": {
        "country": "US",
        "status": "citizen",
        "requiresSponsorship": false
      }
    }
  }'

Profile updates merge into the current candidateContext; the JSON body limit is 256 KB. Upload PDF, DOC, or DOCX as multipart form data under the field file. The maximum file size is 5 MB.

resume.sh
curl https://api.applyguy.ai/v1/profile/resume \
  -X PUT \
  -H "Authorization: Bearer $APPLYGUY_API_KEY" \
  -F "file=@./resume.pdf"

Workday only

Connect the candidate inbox with the bootstrap token

Workday may email a verification code tied to a specific application. Check GET /secrets/status before using Workday. These account-management routes use the short-lived accessToken returned by bootstrap—not the ag_live_… API key.

workday-email.sh
# Authenticate these account routes with bootstrap's accessToken, not ag_live_...
curl https://api.applyguy.ai/secrets/status \
  -H "Authorization: Bearer $APPLYGUY_ACCESS_TOKEN"

curl https://api.applyguy.ai/secrets/email-integration \
  -X PUT \
  -H "Authorization: Bearer $APPLYGUY_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "gmailUser": "candidate@gmail.com",
    "gmailAppPassword": "abcd efgh ijkl mnop"
  }'

Google requires the candidate to enable the appropriate account security settings and create the 16-character Gmail app password once. Apply Guy verifies it over IMAP before encrypting it, never returns it, and preflight reports emailIntegrationRequired and emailIntegrationConnected before credits are reserved.

Step 3

Read the live rate and add credits

Call GET /v1/credits instead of hardcoding rates or purchase bounds. It returns the balance; searchPer25, jobDetail, managed, and agent costs; creditsPerDollar; and the allowed minimum and maximum purchase amounts.

credits.sh
curl https://api.applyguy.ai/v1/credits \
  -H "Authorization: Bearer $APPLYGUY_API_KEY"

curl https://api.applyguy.ai/v1/credits/checkout \
  -X POST \
  -H "Authorization: Bearer $APPLYGUY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "amountCents": 500 }'

Open the returned checkoutUrl for payment. Then poll GET /v1/credits/checkout/{sessionId} until paid. At the current rate, $5 adds 100 credits: 2,000 search pages of up to 25 requested results, 10,000 successful job details, 100 agent-mode applications, or 50 managed applications.

Refunded purchases reverse their corresponding credit grant. A payment dispute freezes protected developer API routes for manual review; those requests return 403 account_frozen.

Step 4

Search the catalog—or bring a supported URL

Catalog reads require both jobs:read and credits:spend. Keeping spend authorization separate means a read-only key created before catalog billing cannot silently consume credits. The U.S.-only jobs API supports text, ATS, remote type, limit, and cursor filters; country is fixed to US in v1. Results are ordered by recency and include the Apply Guy job ID you can pass to preflight and creation. Each successful search costs 0.05 credit per requested block of up to 25 results: limits 25, 50, and 100 cost 0.05, 0.10, and 0.20 respectively. Billing uses the requested limit, even when fewer matches remain.

search.sh
curl -i "https://api.applyguy.ai/v1/jobs?q=software%20engineer&country=US&remote=remote&limit=25" \
  -H "Authorization: Bearer $APPLYGUY_API_KEY"

The -i example displays the four X-ApplyGuy-Credit-* headers. Use the integer Cost-Milli and Balance-Milli values for exact accounting. GET /v1/jobs/{id} costs 0.01 credit only when it returns 200 and is useful when your agent needs the full cached description. Invalid searches, missing or stale details, rate limits, and 5xx responses are not charged.

If your system discovered a listing elsewhere, you may provide exactly one jobUrl instead of jobId. An optional ats hint is accepted; Apply Guy otherwise infers it from the platform-owned host. Catalog IDs get a freshness check during preflight. For raw URLs, preflight validates ATS ownership and URL shape; live availability is resolved when the application runs.

Step 5

Preflight, then create idempotently

Preflight is free. It checks whether the ATS is enabled, whether an inbox connection is required and present, whether the profile and resume are ready, and how many credits the selected mode will use.

preflight.sh
curl https://api.applyguy.ai/v1/applications/preflight \
  -X POST \
  -H "Authorization: Bearer $APPLYGUY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jobId": "951f7024-bbf7-4aa5-98fc-f45625584f9b",
    "mode": "agent"
  }'

If ready is true, create the application. Every create request needs an Idempotency-Key. Retrying the same logical operation with the same key and body returns the original application instead of reserving credits again; reusing a key for another job or mode returns 409 idempotency_conflict. Only one run may be active for the same account and canonical employer target. A prior success returns already_applied; after two failed runs in 24 hours, another create returns application_retry_limit_reached with Retry-After. Rotating keys or changing tracking parameters does not bypass that limit. Application JSON is capped at 256 KB.

Check modeSupported as well as atsEnabled when explaining a blocked preflight. SmartRecruiters is currently managed-only; other enabled platforms can use agent mode.

apply.sh
curl https://api.applyguy.ai/v1/applications \
  -X POST \
  -H "Authorization: Bearer $APPLYGUY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: job-951f7024-jordan-v1" \
  -d '{
    "jobId": "951f7024-bbf7-4aa5-98fc-f45625584f9b",
    "mode": "agent"
  }'

A successful create returns queued. Poll GET /v1/applications/{id} or use webhooks for subsequent states: running, awaiting_answers, success, failed, or cancelled. Read outcomeCode for normalized special outcomes and failureCode for failed applications. success with already_appliedmeans the employer already had this candidate's application, so Apply Guy did not submit a duplicate.

Step 6 · Agent mode only

Treat answer rounds as a typed tool call

Deterministic forms may finish without pausing. When judgment is needed, status becomes awaiting_answers. The answer request contains a prompt, discovered option lists, a responseSchema, and identity fields that bind the answer to this exact form revision.

answer-round.sh
# 1. Fetch the live request after status becomes awaiting_answers
curl "https://api.applyguy.ai/v1/applications/$APPLICATION_ID/answer-request" \
  -H "Authorization: Bearer $APPLYGUY_API_KEY"

# 2. Have your model return JSON matching data.responseSchema

# 3. Submit the exact request identity, fingerprint, and model output
curl "https://api.applyguy.ai/v1/applications/$APPLICATION_ID/answers" \
  -X POST \
  -H "Authorization: Bearer $APPLYGUY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "requestId": "<data.id>",
    "fingerprint": "<data.fingerprint>",
    "answer": <model-output-json>
  }'

The fetched object calls its request UUID id; the answer endpoint deliberately accepts that value as requestId. Generate against the returned schema, not a schema cached from another job. Apply Guy validates the response before re-queuing. A mismatched shape returns 422 answer_schema_invalid; an old request or changed form returns a conflict rather than submitting stale output. Keep the complete answer envelope under 64 KB.

Read the full bring-your-own-agent design guide

Step 7

Listen for state changes

Register a public HTTPS endpoint and choose the lifecycle events you need. The signing secret is returned once. Keep it separate from the API key.

webhook.sh
curl https://api.applyguy.ai/v1/webhooks \
  -X POST \
  -H "Authorization: Bearer $APPLYGUY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/applyguy",
    "events": [
      "application.awaiting_answers",
      "application.succeeded",
      "application.failed"
    ]
  }'

Verify x-applyguy-signature as v1=HMAC_SHA256(secret, timestamp + "." + rawBody). Also reject stale x-applyguy-timestamp values and deduplicate deliveries with x-applyguy-delivery. Delivery is at least once: return a 2xx within 10 seconds; failures retry up to 12 total attempts with exponential backoff.

Step 8

Measure outcomes—and share the operational picture

A key with usage:read can request rolling 24h, 7d, 30d, or 90d reports. The response includes status counts, completion-time p50 and p95, purchased, spent, and refunded credits, time-series buckets, normalized failure reasons, and breakdowns by ATS, mode, and API key.

usage.sh
curl "https://api.applyguy.ai/v1/usage?range=30d" \
  -H "Authorization: Bearer $APPLYGUY_API_KEY"

successRate is a percentage from 0 through 100, rounded to two decimal places. Its denominator is resolved outcomes only: success / (success + failed) × 100. Queued, running, awaiting-answer, and cancelled applications do not distort the rate; a range with no resolved outcomes returns 0.

A key with usage:share can create an expiring, revocable report link. A report contains operational aggregates and no candidate PII. The full URL appears once at creation, cannot be recovered from the list endpoint, and expires after one hour to seven days. Each account can keep at most 20 active links.

share-usage.sh
# Create an expiring report. Its URL is returned only in this response.
curl https://api.applyguy.ai/v1/usage/share-links \
  -X POST \
  -H "Authorization: Bearer $APPLYGUY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "range": "30d", "expiresInSeconds": 86400 }'

# The returned URL has a raw fragment that browsers do not send on navigation:
# https://applyguy.ai/developers/usage#rpt_...

# The report page reads and removes the fragment, then exchanges it in JSON.
curl https://api.applyguy.ai/v1/usage/share-links/exchange \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "token": "rpt_..." }'

Treat the fragment token like a secret. Keep it out of query strings and logs, remove it from browser history immediately, and revoke the link with DELETE /v1/usage/share-links/{id} when it is no longer needed. Expired, revoked, unknown, and malformed tokens all return the same 404 invalid_share_link. Creating a 21st active link returns 409 share_link_limit_reached until one is revoked or expires.

Production behavior

Errors, retries, and credit safety

  • 400 means the request itself is malformed, including a missing idempotency key.
  • 401 means the key is missing or invalid. 403 means the key lacks a required scope—metered catalog reads need both jobs:read and credits:spend—or account_frozen means a payment dispute requires manual review.
  • 402 means the account does not have enough credits for the catalog read or application.
  • 409 covers a disabled ATS, missing inbox integration, stale answer request, or invalid state transition.
  • 413 means the request exceeded the endpoint's documented body limit.
  • 422 covers an incomplete candidate profile or answer JSON that does not match the requested schema.

Errors use a stable error.code, a human-readable error.message, and a requestId for support. Catalog reads charge atomically only when a metered response succeeds. Application credits are reserved atomically at creation. Failures and cancellations refund the reservation only before Apply Guy begins writing the application to the employer. For a single-request ATS that is the final application POST; for a multi-step ATS it is the first non-idempotent account or application write. Once that boundary is crossed, the charge sticks even if the employer rejects it or its response is uncertain. An application waiting for your agent keeps the reservation until it resumes or is cancelled.

Start building

Your first request is the easy part.

The reference covers every endpoint. The quickstart gives you the order, invariants, and retry behavior needed to ship the workflow safely.