openapi: 3.2.0 info: contact: email: support@aiapplyd.com name: AI Applyd url: https://aiapplyd.com description: 'The AI Applyd API runs the whole job hunt for you: it matches you to roles that fit your profile, rewrites your resume for each posting, writes the cover letter the form asks for, and auto-applies across the major applicant tracking systems.' license: name: Proprietary url: https://aiapplyd.com/legal/terms title: AI Applyd Applications API version: 115c47ce servers: - description: Current environment url: https://api.aiapplyd.com/api/v1 security: - BearerAuth: [] tags: - name: Applications paths: /applications: get: tags: - Applications summary: List Applications description: List application results for the authenticated user. parameters: - schema: type: integer maximum: 50 default: 20 description: Page size (max 50) example: 20 exclusiveMinimum: 0 required: false description: Page size (max 50) name: limit in: query - schema: type: integer default: 1 description: Page number (1-based) example: 1 exclusiveMinimum: 0 required: false description: Page number (1-based) name: page in: query - schema: type: string maxLength: 200 description: Search by job title or company name example: Software Engineer required: false description: Search by job title or company name name: search in: query - schema: type: string format: date-time description: Only return results created at or after this ISO timestamp example: '2026-06-12T00:00:00.000Z' required: false description: Only return results created at or after this ISO timestamp name: since in: query - schema: type: string enum: - newest - oldest - best_match - status - company_az default: newest description: 'Sort order: newest, oldest, best_match, status, or company_az' example: newest required: false description: 'Sort order: newest, oldest, best_match, status, or company_az' name: sort in: query - schema: type: string enum: - pending - pending_review - ready_to_submit - applied - applied_unconfirmed - skipped - error - cancelled description: Filter by a single result status example: applied required: false description: Filter by a single result status name: status in: query - schema: type: string description: Filter by multiple result statuses (comma-separated) example: pending,ready_to_submit required: false description: Filter by multiple result statuses (comma-separated) name: statuses in: query - schema: type: string description: Filter by application stage (comma-separated). Independent of status/bucket, which describe the submission lifecycle rather than the hiring conversation. example: callback,phone_screen,interview required: false description: Filter by application stage (comma-separated). Independent of status/bucket, which describe the submission lifecycle rather than the hiring conversation. name: stages in: query - schema: type: string enum: - waiting_for_review - queued_to_apply - verified - submitted - not_landed - taken_down description: Filter by Applications bucket. Selects the newest row of every posting the counter files under that bucket; takes precedence over status / statuses. example: queued_to_apply required: false description: Filter by Applications bucket. Selects the newest row of every posting the counter files under that bucket; takes precedence over status / statuses. name: bucket in: query responses: '200': description: Application results list content: application/json: schema: $ref: '#/components/schemas/ApplicationResultListResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplications /applications/usage: get: tags: - Applications summary: Get Apply Usage description: 'Returns the user''s rolling 30-day auto-apply cap: used, limit, resetAt (ISO), allowed.' responses: '200': description: Rolling-30d auto-apply cap status content: application/json: schema: $ref: '#/components/schemas/ApplicationsUsageResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsUsage /applications/prepare: post: tags: - Applications summary: Prepare Application Package description: Tailor resume and generate cover letter for a specific job match using AI. requestBody: content: application/json: schema: $ref: '#/components/schemas/PrepareApplicationRequest' responses: '200': description: Application package prepared content: application/json: schema: $ref: '#/components/schemas/PrepareApplicationResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsPrepare /applications/results/approve-batch: post: tags: - Applications summary: Bulk Approve Pending Applications description: Approve up to 25 pending_review results in one request. Each row is re-validated server-side (preflight + platform submittability + status guard) and enqueued independently. Per-row failures do not abort sibling rows. requestBody: content: application/json: schema: $ref: '#/components/schemas/BulkApproveRequest' responses: '200': description: Per-row approval verdicts content: application/json: schema: $ref: '#/components/schemas/BulkApproveResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsResultsApproveBatch /applications/by-id/{resultId}: get: tags: - Applications summary: Get application result by ID description: Get one application result owned by the authenticated user. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Application result content: application/json: schema: $ref: '#/components/schemas/ApplicationResultItemResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByIdByResultId /applications/{resultId}/approve: post: tags: - Applications summary: Approve Pending Application description: Approve a pending_review application in copilot mode, changing its status to ready_to_submit. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Application approved content: application/json: schema: $ref: '#/components/schemas/ApproveResultResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdApprove /applications/{resultId}/reject: post: tags: - Applications summary: Reject Pending Application description: Reject a pending_review application in copilot mode, changing its status to skipped. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Application rejected content: application/json: schema: $ref: '#/components/schemas/RejectResultResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdReject /applications/{resultId}/retry: post: tags: - Applications summary: Retry Failed Submission (Admin Only) description: 'Admin-only. Retry a failed application submission. Resets the result status and re-enqueues for submission. Returns 403 for non-admin users (2026-07-06: there is no user-facing retry).' parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Submission retry queued content: application/json: schema: $ref: '#/components/schemas/ApproveResultResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdRetry /applications/{resultId}/retry-prep: post: tags: - Applications summary: Retry Failed Preparation (Admin Only) description: 'Admin-only. Retry a failed or stuck application preparation. Resets the result and re-enqueues for preparation. Returns 403 for non-admin users (2026-07-06: there is no user-facing retry).' parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Preparation retry queued content: application/json: schema: $ref: '#/components/schemas/ApproveResultResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdRetryPrep /applications/{resultId}/cancel: post: tags: - Applications summary: Cancel Pre-Submission Application description: Cancel an in-flight auto-apply ONLY while it's still queued or preparing. Returns 409 Conflict once a Browserbase session has been spawned, the preparer has flipped into SUBMITTING, or the row has reached a terminal state. Used by auto-apply mode where there is no approve button so the user can still bail out before any cloud-browser cost is committed. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Application cancelled before submission content: application/json: schema: $ref: '#/components/schemas/CancelResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdCancel /applications/{resultId}/screenshot/{variant}: get: tags: - Applications summary: View Submission Screenshot description: Download a before/after submission screenshot captured by the auto-apply submitter. Returns the raw PNG bytes. Auth-gated by session because screenshots may contain form PII. parameters: - schema: type: string pattern: ^\d+$ description: Application result ID example: '1' required: true description: Application result ID in: path name: resultId - schema: type: string enum: - before - after description: 'Which capture to serve: `before` (pre-submit) or `after` (post-submit).' example: before required: true description: 'Which capture to serve: `before` (pre-submit) or `after` (post-submit).' in: path name: variant responses: '200': description: Screenshot image (PNG) content: image/png: schema: type: string format: binary '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdScreenshotByVariant /applications/by-job-match/{jobMatchId}: get: tags: - Applications summary: Get application result by job match ID description: Get the most recent application result for a given job match. parameters: - schema: type: string pattern: ^\d+$ description: Job match identifier example: '1' required: true description: Job match identifier in: path name: jobMatchId responses: '200': description: Application result content: application/json: schema: $ref: '#/components/schemas/SingleResultResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByJobMatchByJobMatchId /applications/{resultId}/live-view: get: tags: - Applications summary: Get Browserbase Live View URL description: 'Returns a freshly-signed Browserbase debuggerFullscreenUrl that the web app can embed in an iframe to show the in-progress apply session live. Returns `available: false` once the run reaches a terminal state.' parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Live view URL or unavailable marker content: application/json: schema: $ref: '#/components/schemas/LiveViewResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdLiveView /applications/{resultId}/stage: patch: tags: - Applications summary: Update Application Stage description: Update the application stage (e.g. applied, interview, offered) for a specific application result. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId requestBody: content: application/json: schema: $ref: '#/components/schemas/UpdateApplicationStageRequest' responses: '200': description: Application stage updated content: application/json: schema: $ref: '#/components/schemas/UpdateApplicationStageResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: patchApplicationsByResultIdStage /applications/{resultId}/extract-form: post: tags: - Applications summary: Extract and map form fields for an application description: Run form extractor, AI-map fields, AI-answer screening questions, and return proposed form values for copilot review. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Extracted form fields and screening answers content: application/json: schema: $ref: '#/components/schemas/ExtractFormResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdExtractForm /applications/{resultId}/form-values: put: tags: - Applications summary: Update form values before submission description: Accept user-edited form field values and screening answers before submitting the application. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId requestBody: content: application/json: schema: $ref: '#/components/schemas/FormValuesRequest' responses: '200': description: Form values updated content: application/json: schema: $ref: '#/components/schemas/FormValuesResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: putApplicationsByResultIdFormValues /applications/{resultId}/download/{type}: get: tags: - Applications summary: Download result PDF description: Download the tailored resume or cover letter PDF for a specific application result. parameters: - schema: type: string pattern: ^\d+$ description: Application result ID example: '1' required: true description: Application result ID in: path name: resultId - schema: type: string enum: - resume - cover-letter description: Type of document to download example: resume required: true description: Type of document to download name: type in: path responses: '200': description: PDF document binary content: application/pdf: schema: type: string format: binary '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdDownloadByType /applications/{resultId}/submission-info: get: tags: - Applications summary: Get Submission Activity Info description: 'Get detailed submission activity: screenshots availability, form field log, submission attempts, and activity timeline.' parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Submission activity details content: application/json: schema: $ref: '#/components/schemas/ScreenshotInfoResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdSubmissionInfo /applications/{resultId}/generate-outreach: post: tags: - Applications summary: Generate Recruiter Outreach Messages description: Generate personalized LinkedIn connection requests, follow-up messages, and cold emails for a specific application result. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Outreach messages generated content: application/json: schema: $ref: '#/components/schemas/GenerateOutreachResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdGenerateOutreach /applications/{resultId}/refine: post: tags: - Applications summary: Refine Application Document description: Regenerate a tailored resume or cover letter with custom user instructions. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId requestBody: content: application/json: schema: $ref: '#/components/schemas/RefineDocumentRequest' responses: '200': description: Document refinement started content: application/json: schema: $ref: '#/components/schemas/RefineDocumentResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdRefine /applications/{resultId}/document: patch: tags: - Applications summary: Apply Document Patch description: Persist a chat-edited tailored resume or cover letter and regenerate its PDF. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId requestBody: content: application/json: schema: $ref: '#/components/schemas/ApplyDocumentPatchRequest' responses: '200': description: Patch applied and PDF regenerated content: application/json: schema: $ref: '#/components/schemas/ApplyDocumentPatchResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: patchApplicationsByResultIdDocument /applications/{resultId}/parse-tailored-resume: post: tags: - Applications summary: Parse Tailored Resume Markdown description: Parse the application's tailored resume markdown into structured ResumeBlockEditor-shaped data so the Refine-with-AI modal can render the live ResumeTemplate preview and Form view from the same source the resume-builder uses. Reuses parseResumeAIData (Gemini 2.5 Flash, structured output). parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Structured resume data content: application/json: schema: $ref: '#/components/schemas/ParseTailoredResumeResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdParseTailoredResume /applications/{resultId}/staleness: get: tags: - Applications summary: Get prepared application staleness description: Returns whether any prepared step on this application_result is stale relative to the user's current AI settings, and which steps would re-run on /re-prepare. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Staleness assessment for the prepared application content: application/json: schema: $ref: '#/components/schemas/StalenessResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdStaleness /applications/{resultId}/re-prepare: post: tags: - Applications summary: Re-prepare a stale application description: Re-runs only the listed prepare steps (or the server-recomputed stale steps when none are provided), preserving the outputs of any step not re-run. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId requestBody: content: application/json: schema: $ref: '#/components/schemas/RePrepareRequest' responses: '200': description: Application re-prepared content: application/json: schema: $ref: '#/components/schemas/RePrepareResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdRePrepare /applications/{resultId}/switch-document: post: tags: - Applications summary: Switch Bound Document description: Swap the bound resume / cover letter on an application result to base, an existing tailored doc, or any user-owned document by id. No AI tokens are consumed. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId requestBody: content: application/json: schema: $ref: '#/components/schemas/SwitchDocumentRequest' responses: '200': description: Bound document switched content: application/json: schema: $ref: '#/components/schemas/SwitchDocumentResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdSwitchDocument /applications/{resultId}/negotiate: get: tags: - Applications summary: Get Negotiation Scripts description: Returns 3 to 5 offer-specific negotiation scripts for the given application_result. Generates on first call, then serves from KV cache for 7 days. Requires the application to be in the `offered` stage; otherwise responds 422. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Negotiation scripts content: application/json: schema: $ref: '#/components/schemas/NegotiationResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdNegotiate post: tags: - Applications summary: Regenerate Negotiation Scripts description: 'Force a fresh AI generation, bypassing the KV cache. When `force: true`, also bypasses the `offered` stage gate so users can prep before the offer drops.' parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId requestBody: content: application/json: schema: $ref: '#/components/schemas/NegotiateRegenerateRequest' responses: '200': description: Regenerated negotiation scripts content: application/json: schema: $ref: '#/components/schemas/NegotiationResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdNegotiate /applications/{resultId}/generation-status: get: tags: - Applications summary: Get AI Generation Status description: Returns the current application stage and the lifecycle status of the interview-prep and negotiation-coach generations for this application result. Read-only - never triggers a paid AI generation. Used by the frontend to poll real status and to decide whether the negotiation gate is unlocked. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Generation status snapshot content: application/json: schema: $ref: '#/components/schemas/GenerationStatusResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdGenerationStatus /applications/{resultId}/queue-position: get: tags: - Applications summary: Get Apply Queue Position description: 'Returns this application result''s live position in the platform-wide auto-apply queue: 1-based rank (oldest-first, matching the dispatcher''s `ORDER BY created_at ASC`), how many are ahead, the total queue depth, whether it is already processing, and a rough wait estimate. Read-only - two cheap indexed COUNT reads, never triggers any work. Polled by the client while a row is waiting / retrying / processing.' parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Live queue-position snapshot content: application/json: schema: $ref: '#/components/schemas/QueuePositionResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdQueuePosition /applications/pipeline-status: get: tags: - Applications summary: Get Apply Pipeline Status description: 'Returns the caller''s live apply-pipeline snapshot: platform-wide queue depth, how many of the caller''s rows are waiting / processing, and the frontmost platform-wide rank of the caller''s active rows. Read-only - a few cheap indexed COUNT reads, never triggers any work. Polled by the persistent top-of-page pipeline bar on the Applications screen.' responses: '200': description: Live apply-pipeline snapshot content: application/json: schema: $ref: '#/components/schemas/PipelineStatusResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsPipelineStatus /applications/{jobId}/level-strategy: post: tags: - Applications summary: Generate Level Strategy (Block C) description: 'Generate the Block C level strategy for a job/candidate pair. Produces ONE of two parallel plans depending on whether the candidate''s natural level matches/exceeds the JD level ("sell senior") or sits above it ("downlevel play"). Cache-first: served from KV for 7 days unless `force: true`.' parameters: - schema: type: string pattern: ^\d+$ description: Job listing identifier example: '1' required: true description: Job listing identifier in: path name: jobId requestBody: content: application/json: schema: $ref: '#/components/schemas/LevelStrategyRequest' responses: '200': description: Level strategy data content: application/json: schema: $ref: '#/components/schemas/LevelStrategyResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByJobIdLevelStrategy /applications/personalization-plan: post: tags: - Applications summary: Generate Personalization Plan description: Block E of the structured evaluation. Returns the top 5 CV changes + top 5 LinkedIn changes scoped to the job match's archetype, plus 8-15 ATS keywords from the JD. Requires the upstream evaluator (Block A) to have classified the archetype on the job match row; otherwise responds 400. requestBody: content: application/json: schema: $ref: '#/components/schemas/PersonalizationPlanRequest' responses: '200': description: Personalization plan content: application/json: schema: $ref: '#/components/schemas/PersonalizationPlanResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsPersonalizationPlan /applications/recover-stuck: post: tags: - Applications summary: Recover Stuck Applications description: Trigger on-demand recovery of stuck applications for the current user. Marks timed-out preparations as failed. responses: '200': description: Recovery complete content: application/json: schema: $ref: '#/components/schemas/RecoverStuckResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsRecoverStuck /applications/{resultId}/ai-edit/open: post: tags: - Applications summary: Open AI Edit Session description: Snapshot the application's currently-bound resume into a KV-backed draft. Returns a fresh sessionId per call. Draft TTL is 60 minutes from the last mutation. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId requestBody: content: application/json: schema: $ref: '#/components/schemas/AiEditOpenRequest' responses: '200': description: Session opened with snapshot content: application/json: schema: $ref: '#/components/schemas/AiEditOpenResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdAiEditOpen /applications/{resultId}/ai-edit/rewind: post: tags: - Applications summary: Rewind AI Edit Session description: Drop every step with messageIdx >= the supplied value. The draft is restored from the snapshot taken just before the cut. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId requestBody: content: application/json: schema: $ref: '#/components/schemas/AiEditRewindRequest' responses: '200': description: Draft rewound content: application/json: schema: $ref: '#/components/schemas/AiEditRewindResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdAiEditRewind /applications/{resultId}/ai-edit/finalize: post: tags: - Applications summary: Finalize AI Edit Session description: Atomically create a new user_documents row from the draft, point the application result's tailoredResumeDocId at it, and delete the KV draft. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId requestBody: content: application/json: schema: $ref: '#/components/schemas/AiEditFinalizeRequest' responses: '200': description: Draft finalized and bound content: application/json: schema: $ref: '#/components/schemas/AiEditFinalizeResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdAiEditFinalize /applications/{resultId}/ai-edit/preview: get: tags: - Applications summary: Preview AI Edit Draft description: Render the current draft as a PDF. Template is forced to ATS-optimized. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId - schema: type: string minLength: 1 maxLength: 64 required: true name: sessionId in: query responses: '200': description: Draft PDF content: application/pdf: schema: type: string format: binary '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdAiEditPreview /applications/{resultId}/ai-edit/available-scopes: get: tags: - Applications summary: List AI Edit Scopes Available For This Application description: Returns one entry per AiEditScope, telling the UI which are pickable for this application (e.g. cover_letter is unavailable when none has been generated). parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Per-scope availability map content: application/json: schema: $ref: '#/components/schemas/AiEditAvailableScopesResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdAiEditAvailableScopes /applications/{resultId}/ats-credentials: get: tags: - Applications summary: List Manufactured ATS Accounts description: List the candidate accounts AI Applyd created on the user's behalf for this application (auth-walled ATS lane). Never returns passwords. parameters: - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Manufactured ATS accounts for the application content: application/json: schema: type: object properties: data: type: object properties: credentials: type: array items: $ref: '#/components/schemas/AtsCredentialSummary' required: - credentials additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: getApplicationsByResultIdAtsCredentials /applications/{resultId}/ats-credentials/{credentialId}/reveal: post: tags: - Applications summary: Reveal Manufactured ATS Account Password description: Decrypt + return the password of a manufactured ATS account. The reveal is recorded in the audit log. parameters: - schema: type: string pattern: ^\d+$ description: Manufactured ATS credential identifier example: '1' required: true description: Manufactured ATS credential identifier in: path name: credentialId - schema: type: string pattern: ^\d+$ description: Application result identifier example: '1' required: true description: Application result identifier in: path name: resultId responses: '200': description: Decrypted credentials content: application/json: schema: type: object properties: data: type: object properties: loginUrl: type: - string - 'null' password: type: string description: Decrypted account password (audit-logged on reveal) platform: type: string username: type: string required: - loginUrl - password - platform - username additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '404': description: Not Found content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' operationId: postApplicationsByResultIdAtsCredentialsByCredentialIdReveal components: schemas: PrepareApplicationRequest: type: object properties: jobMatchId: type: integer description: ID of the job match to prepare application for example: 42 exclusiveMinimum: 0 mode: type: string enum: - copilot - auto_approve description: Override mode for this preparation. When "copilot", result is created as pending_review. example: copilot required: - jobMatchId additionalProperties: false LiveViewResponse: type: object properties: data: $ref: '#/components/schemas/LiveViewData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response ParsedTailoredResumePersonalInfo: type: object properties: email: type: - string - 'null' fullName: type: string linkedin: type: - string - 'null' location: type: - string - 'null' phone: type: - string - 'null' title: type: - string - 'null' website: type: - string - 'null' required: - fullName additionalProperties: false GenerationStatusData: type: object properties: applicationStage: type: string enum: - applied - callback - phone_screen - interview - offered - rejected - no_response description: Current stage of this application. NULL rows are coalesced to the default `applied` so the client always has a concrete value. example: applied interviewPrepStatus: type: string enum: - idle - generating - completed - failed description: Interview-prep generation lifecycle (idle | generating | completed | failed). example: idle hasInterviewPrep: type: boolean description: True when interview-prep content has been generated and persisted. example: false negotiationStatus: type: string enum: - idle - generating - completed - failed description: Negotiation-coach generation lifecycle (idle | generating | completed | failed). example: idle hasNegotiation: type: boolean description: True when negotiation scripts have been generated and persisted. example: false negotiationUnlocked: type: boolean description: True when `applicationStage === "offered"`. When false the negotiation gate blocks generation; the client should surface "mark as Offered to unlock". example: false jobListingId: type: - integer - 'null' description: PK of the linked job_listing that owns the interview-prep content. NULL when this result is not linked to a job match / listing. required: - applicationStage - interviewPrepStatus - hasInterviewPrep - negotiationStatus - hasNegotiation - negotiationUnlocked - jobListingId additionalProperties: false BulkApproveResponse: type: object properties: data: type: object properties: results: type: array items: $ref: '#/components/schemas/BulkApproveResultEntry' totalAttempted: type: integer minimum: 0 totalApproved: type: integer minimum: 0 failedResultIds: type: array items: type: string description: Result IDs that failed in this batch (subset of `resultIds` from the request). Empty array when every row succeeded. required: - results - totalAttempted - totalApproved - failedResultIds additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response BulkApproveResultEntry: type: object properties: id: type: string description: Result ID echoed back from the request. ok: type: boolean status: type: string enum: - pending - pending_review - ready_to_submit - applied - applied_unconfirmed - skipped - error - cancelled description: New status when ok=true (always ready_to_submit). example: pending reason: type: string description: Machine-readable reason when ok=false (for example "not_pending_review", "platform_unsupported", "preflight_failed", "monthly_cap", or "subscription_required"). required: - id - ok additionalProperties: false SwitchDocumentResponse: type: object properties: data: $ref: '#/components/schemas/SwitchDocumentResponseData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response CancelResultData: type: object properties: id: type: integer status: type: string enum: - pending - pending_review - ready_to_submit - applied - applied_unconfirmed - skipped - error - cancelled description: Status of an individual application result example: pending required: - id - status additionalProperties: false ScreenshotInfoData: type: object properties: alreadyAppliedProof: type: - object - 'null' properties: notice: type: string minLength: 1 maxLength: 500 pageUrl: type: - string - 'null' maxLength: 2048 screenshotUrl: type: - string - 'null' maxLength: 2048 seenAt: type: string minLength: 1 source: type: string enum: - post_submit_page - self_judge - vision_page_text required: - notice - pageUrl - screenshotUrl - seenAt - source description: 'Evidence behind an already_applied verdict: the employer page''s own notice, its URL and the screenshot of that page. Null when the verdict has no employer-page proof. Detail projection only.' committedFields: type: - array - 'null' items: type: object properties: attempt: type: integer minimum: 1 enteredValue: type: - string - 'null' maxLength: 512 label: type: string minLength: 1 maxLength: 200 lane: type: string minLength: 1 maxLength: 160 phase: type: string minLength: 1 maxLength: 64 provenance: type: string enum: - profile - answer_context - document - derived - generated - guessed - unsourced description: Where the value committed into an employer form came from example: profile source: type: string minLength: 1 maxLength: 64 value: type: - string - 'null' maxLength: 512 valueShape: type: string minLength: 1 maxLength: 32 verified: type: boolean required: - attempt - label - phase - provenance - value - valueShape - verified additionalProperties: false maxItems: 128 description: Per-field record of the values committed into the employer form, with raw value, provenance and a read-back verified flag. A read-back of our own write - never evidence an application landed. Null on historical rows. identityCommitted: type: - object - 'null' properties: email: type: - boolean - 'null' firstName: type: - boolean - 'null' lastName: type: - boolean - 'null' required: - email - firstName - lastName additionalProperties: false description: Which of firstName/lastName/email read back present at the submit click. A read-back of our own write - MUST NEVER be used to score whether an application landed. Per-member null means UNOBSERVED, never false. Null on historical rows. phaseTimings: type: - object - 'null' properties: aggregate: type: integer minimum: 0 captchaMs: type: integer minimum: 0 currentPhase: type: string enum: - prepare - navigate - login - fill - submit - verify - aggregate - unknown description: Coarse-grained phase where a submission failure occurred example: submit currentPhaseMs: type: integer minimum: 0 employerMailWaitMs: type: integer minimum: 0 fill: type: integer minimum: 0 fillPerAttempt: type: array items: type: integer minimum: 0 login: type: integer minimum: 0 msToSubmitPress: type: integer minimum: 0 navigate: type: integer minimum: 0 prepare: type: integer minimum: 0 prepareStep: type: string maxLength: 160 slowestSteps: type: array items: type: object properties: ms: type: integer minimum: 0 ourMs: type: integer minimum: 0 step: type: string maxLength: 160 waitedOnEmployerMailMs: type: integer minimum: 0 required: - ms - step additionalProperties: false submit: type: integer minimum: 0 submitPerAttempt: type: array items: type: integer minimum: 0 totalMs: type: integer minimum: 0 unaccountedMs: type: integer minimum: 0 unknown: type: integer minimum: 0 verify: type: integer minimum: 0 required: - totalMs - unaccountedMs additionalProperties: false description: Per-phase wall clock for the run, keyed on the failure-phase enum, plus totalMs, captchaMs and unaccountedMs. An absent phase key is UNOBSERVED, never zero. Null on historical rows. hasPreFill: type: boolean description: Whether a pre-fill screenshot exists hasPostSubmit: type: boolean description: Whether a post-submit screenshot exists formFieldsLog: type: - array - 'null' items: $ref: '#/components/schemas/FormFieldsLogEntry' description: Detailed log of form fields that were filled submissionAttempts: type: - array - 'null' items: anyOf: - type: object properties: detail: type: string durationMs: type: integer minimum: 0 error: type: string replayUrl: type: string format: uri screenshotKeys: type: array items: type: string skippedOptionalFieldCount: type: integer minimum: 0 strategy: type: string enum: - direct_api - form_post - linkedin_easy_apply - indeed_apply - glassdoor_apply - ziprecruiter_apply - authenticated_browser - workday_navigator - ai_browser_agent - email_fallback description: Strategy used to submit a job application example: direct_api success: type: boolean targetUrl: type: string timestamp: type: string required: - strategy - success - timestamp additionalProperties: false - type: object properties: detail: type: string durationMs: type: integer minimum: 0 error: type: string phase: type: string enum: - preparation - submission - dispatcher - queue_consumer - inline_fallback - orphan_recovery - unknown strategy: type: string success: type: boolean timestamp: type: string required: - detail - phase - strategy - success - timestamp description: Submission strategy attempts with timestamps activityLog: type: - array - 'null' items: type: object properties: details: type: string durationMs: type: number status: type: string enum: - success - error - info description: Status of an individual step in an activity log example: info step: type: string timestamp: type: string required: - status - step - timestamp additionalProperties: false description: Step-by-step activity timeline required: - hasPreFill - hasPostSubmit - formFieldsLog - submissionAttempts - activityLog additionalProperties: false AiEditRewindRequest: type: object properties: messageIdx: type: integer minimum: 0 description: Drop every step with messageIdx >= this value. messageIdx=0 wipes the session back to originalContent. example: 2 sessionId: type: string minLength: 1 maxLength: 64 required: - messageIdx - sessionId additionalProperties: false UpdateApplicationStageRequest: type: object properties: applicationStage: type: string enum: - applied - callback - phone_screen - interview - offered - rejected - no_response description: Stage of the job application pipeline example: applied required: - applicationStage additionalProperties: false RePrepareRequest: type: object properties: steps: type: array items: type: string enum: - quality_gate - company_intel - tailor_resume - translate - cover_letter description: A single preparation step within the application-preparer pipeline example: tailor_resume maxItems: 5 description: Explicit prepare steps to re-run. Omit to use the server-computed stale steps. example: - tailor_resume - cover_letter additionalProperties: false description: Re-prepare request body. GenerationStatusResponse: type: object properties: data: $ref: '#/components/schemas/GenerationStatusData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response AiEditOpenRequest: type: object properties: scope: anyOf: - type: string enum: - tailored_resume - base_resume - cover_letter description: Which document the AI edit session refines. example: tailored_resume - type: string enum: - resume description: Which document the session refines. Accepts the legacy `resume` alias for backwards compatibility (mapped to `tailored_resume`). example: tailored_resume additionalProperties: false AIResumeData: type: - object - 'null' properties: certifications: type: array items: type: string education: type: array items: $ref: '#/components/schemas/EducationEntry' experience: type: array items: $ref: '#/components/schemas/ExperienceEntry' personalInfo: $ref: '#/components/schemas/PersonalInfo' skills: type: array items: type: string summary: type: - string - 'null' SwitchDocumentRequest: type: object properties: kind: type: string enum: - resume - cover_letter description: Which bound document to swap on the application result. example: resume target: type: string enum: - base - tailored - document_id description: Where to point the bound document. "base" picks the user's base resume/cover-letter; "tailored" keeps the existing tailored doc; "document_id" requires `documentId` and binds to a user-owned document by id. example: base documentId: type: integer description: Required when target is "document_id" - must reference a user-owned document of the matching type. example: 42 exclusiveMinimum: 0 required: - kind - target additionalProperties: false ApplyDocumentPatchResponse: type: object properties: data: type: object properties: id: type: integer documentType: type: string enum: - resume - cover-letter description: Type of PDF document to download example: resume content: type: string description: The normalized final content that was persisted and used to regenerate the PDF structuredResume: type: - object - 'null' properties: certifications: type: array items: type: string education: type: array items: $ref: '#/components/schemas/EducationEntry' experience: type: array items: $ref: '#/components/schemas/ExperienceEntry' personalInfo: $ref: '#/components/schemas/PersonalInfo' skills: type: array items: type: string summary: type: - string - 'null' additionalProperties: false description: The stored structured tailored-resume snapshot after canonical relay-email enforcement. required: - id - documentType - content additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response ParsedTailoredResumeEducation: type: object properties: degree: type: string endDate: type: - string - 'null' gpa: type: - string - 'null' highlights: type: - array - 'null' items: type: string institution: type: string location: type: - string - 'null' startDate: type: - string - 'null' required: - degree - institution additionalProperties: false DownlevelPlan: type: - object - 'null' properties: acceptanceCriteria: $ref: '#/components/schemas/DownlevelAcceptanceCriteria' promotionCriteria: type: array items: type: string minLength: 1 maxLength: 280 minItems: 3 maxItems: 5 description: 3 to 5 clear, measurable promotion criteria to negotiate up front. Each must be a concrete observable, not a vague behavior. walkawayConditions: type: array items: type: string minLength: 1 maxLength: 280 minItems: 2 maxItems: 3 description: 2 to 3 hard conditions under which the candidate should decline the offer outright. required: - acceptanceCriteria - promotionCriteria - walkawayConditions additionalProperties: false description: Non-null only when direction == 'downlevel'. ApplyDocumentPatchRequest: type: object properties: documentType: type: string enum: - resume - cover-letter description: 'Which document the applied patch mutated: resume or coverLetter' example: resume content: type: string minLength: 1 maxLength: 200000 description: Final document markdown after client-applied chat patches patchCount: type: integer minimum: 1 maximum: 100 description: Number of DocumentPatch entries the client applied to produce `content` example: 3 structuredResume: type: object properties: certifications: type: array items: type: string education: type: array items: $ref: '#/components/schemas/EducationEntry' experience: type: array items: $ref: '#/components/schemas/ExperienceEntry' personalInfo: $ref: '#/components/schemas/PersonalInfo' skills: type: array items: type: string summary: type: - string - 'null' additionalProperties: false description: Final structured tailored-resume snapshot. Resume clients send this beside content so section edits remain available to form and template views. required: - documentType - content - patchCount additionalProperties: false AiEditFinalizeResponse: type: object properties: data: type: object properties: documentId: type: integer exclusiveMinimum: 0 resultId: type: integer exclusiveMinimum: 0 version: type: integer exclusiveMinimum: 0 required: - documentId - resultId - version additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response PersonalizationPlanResponse: type: object properties: data: $ref: '#/components/schemas/PersonalizationPlanData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response ExperienceEntry: type: object properties: bullets: type: array items: type: string example: - Led migration of monolithic architecture to microservices, reducing deployment time by 60% company: type: string example: Acme Corp current: type: - boolean - 'null' endDate: type: - string - 'null' example: 2024-01 location: type: - string - 'null' startDate: type: string example: 2020-01 title: type: string example: Senior Engineer required: - bullets - company - startDate - title additionalProperties: false AiEditRewindResponse: type: object properties: data: type: object properties: draft: $ref: '#/components/schemas/AiEditDraft' droppedSteps: type: integer minimum: 0 sessionId: type: string required: - draft - droppedSteps - sessionId additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response SuggestedContact: type: object properties: role: type: string description: Contact role (e.g. Hiring Manager, Recruiter) example: Hiring Manager searchUrl: type: string description: LinkedIn search URL to find this contact example: https://linkedin.com/search/results/people/?keywords=... emailPattern: type: string description: Guessed email pattern for the company example: first.last@company.com required: - role - searchUrl - emailPattern additionalProperties: false RecoverStuckResponse: type: object properties: data: type: object properties: id: type: integer recovered: type: integer status: type: string enum: - none_stuck - recovered description: Recovery operation result status example: recovered required: - id - recovered - status additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response PersonalInfo: type: object properties: email: anyOf: - type: string format: email - type: string enum: - '' - {} example: name@example.com fullName: type: - string - 'null' example: Ada Lovelace linkedin: type: - string - 'null' location: type: - string - 'null' example: San Francisco, CA phone: type: - string - 'null' example: +1 (555) 123-4567 title: type: - string - 'null' example: Senior Software Engineer website: type: - string - 'null' additionalProperties: false ContactTypeMessage: type: object properties: linkedinNote: type: string maxLength: 300 description: LinkedIn note tailored to this audience (max 300 chars) emailSubject: type: string description: Email subject line for this audience emailBody: type: string description: Email body for this audience required: - linkedinNote - emailSubject - emailBody additionalProperties: false description: 'Recruiter outreach: Fit / Proof / "Happy to share my CV"' NegotiationFollowUpResponse: type: object properties: response: type: string minLength: 1 maxLength: 2000 description: Ready-to-paste reply the user can send verbatim trigger: type: string minLength: 1 maxLength: 400 description: Recruiter pushback this response handles (e.g. "we have a hard cap") example: We do not have room to move on base salary required: - response - trigger additionalProperties: false StepPlanResponseData: type: object properties: stepsRun: type: array items: type: string enum: - quality_gate - company_intel - tailor_resume - translate - cover_letter description: A single preparation step within the application-preparer pipeline example: tailor_resume stepsSkipped: type: array items: type: object properties: reason: type: string step: type: string enum: - quality_gate - company_intel - tailor_resume - translate - cover_letter description: A single preparation step within the application-preparer pipeline example: tailor_resume required: - reason - step additionalProperties: false description: A step the server will skip on the next re-prepare run, with a human-readable reason. required: - stepsRun - stepsSkipped additionalProperties: false description: Projected re-prepare plan - which stale steps would actually run vs. be skipped (and why) under the user's current AI persona. RejectResultResponse: type: object properties: data: type: object properties: id: type: integer status: type: string enum: - pending - pending_review - ready_to_submit - applied - applied_unconfirmed - skipped - error - cancelled description: Status of an individual application result example: pending required: - id - status additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response ApproveResultResponse: type: object properties: data: type: object properties: id: type: integer status: type: string enum: - pending - pending_review - ready_to_submit - applied - applied_unconfirmed - skipped - error - cancelled description: Status of an individual application result example: pending required: - id - status additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response LinkedinChange: type: object properties: currentState: type: string minLength: 1 maxLength: 400 description: One-sentence excerpt of what the LinkedIn section likely contains. When the profile is not stored, assume a typical career-ops style profile. priority: type: string enum: - high - medium - low description: How impactful this change is for the targeted role example: high proposedChange: type: string minLength: 1 maxLength: 400 description: Specific edit to apply, citing JD vocabulary in native tech English rationale: type: string minLength: 1 maxLength: 600 description: Why this edit closes a gap or amplifies a strength for THIS archetype section: type: string enum: - headline - about - featured - experience - skills description: LinkedIn profile section the proposed change targets example: headline required: - currentState - priority - proposedChange - rationale - section additionalProperties: false LevelStrategyResponseData: type: object properties: cached: type: boolean description: True when the response was served from KV cache. example: false data: $ref: '#/components/schemas/LevelStrategyData' required: - cached - data additionalProperties: false ExtractFormField: type: object properties: field: type: string maxLength: 500 value: type: string maxLength: 10000 selector: type: - string - 'null' maxLength: 2000 action: type: string maxLength: 100 required: - field - value - selector - action additionalProperties: false RePrepareResponse: type: object properties: data: $ref: '#/components/schemas/RePrepareResponseData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response ApplicationsUsageResponse: type: object properties: data: type: object properties: allowed: type: boolean description: Whether the user can enqueue another auto-apply right now (false = cap reached). limit: type: integer minimum: 0 description: Tier-bound rolling-30d auto-apply cap (e.g. 7 for job_seeker, 100 for hired_in_30, 300 for hired_yesterday). example: 7 resetAt: type: string description: ISO timestamp when the current rolling window rolls over (i.e. when the oldest counted apply ages out). example: '2026-05-20T00:00:00.000Z' used: type: integer minimum: 0 description: Auto-apply submissions counted against the rolling-30d cap. example: 3 required: - allowed - limit - resetAt - used additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response SingleResultResponse: type: object properties: data: $ref: '#/components/schemas/SingleResultData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response AiEditAvailableScope: type: object properties: available: type: boolean reason: type: string maxLength: 200 description: Human-readable reason why this scope is unavailable. Only present when `available` is false. scope: type: string enum: - tailored_resume - base_resume - cover_letter description: Which document the AI edit session refines. example: tailored_resume required: - available - scope additionalProperties: false SellSeniorPlan: type: - object - 'null' properties: founderAdvantage: type: - string - 'null' minLength: 1 maxLength: 500 description: Ownership-signal framing when the candidate has founder/builder background; null when no such proof point exists in the resume. framingPhrases: type: array items: type: string minLength: 1 maxLength: 200 minItems: 3 maxItems: 5 description: 3 to 5 short phrases the candidate can use verbatim to frame seniority claims. leadAchievements: type: array items: type: string minLength: 1 maxLength: 280 minItems: 3 maxItems: 5 description: 3 to 5 short bullets of achievements to lead with. MUST cite proof points actually present in the candidate's resume; never invent metrics. required: - founderAdvantage - framingPhrases - leadAchievements additionalProperties: false description: Non-null only when direction is 'at_level' or 'stretch_up'. AiEditDraftSections: type: object properties: education: type: string experience: type: string skills: type: string summary: type: string required: - education - experience - skills - summary additionalProperties: false StalenessResponseData: type: object properties: documentsOutdatedAt: type: - string - 'null' description: ISO timestamp when the row was marked out-of-sync, or null when no marker is persisted. plan: $ref: '#/components/schemas/StepPlanResponseData' reasons: type: array items: type: object properties: message: type: string step: type: string enum: - quality_gate - company_intel - tailor_resume - translate - cover_letter description: A single preparation step within the application-preparer pipeline example: tailor_resume required: - message - step additionalProperties: false description: A single reason a prepared step is now out-of-date. repreparable: type: boolean description: False when re-prepare is blocked because the application has already entered a submission/terminal phase. stale: type: boolean staleSteps: type: array items: type: string enum: - quality_gate - company_intel - tailor_resume - translate - cover_letter description: A single preparation step within the application-preparer pipeline example: tailor_resume required: - documentsOutdatedAt - plan - reasons - repreparable - stale - staleSteps additionalProperties: false LevelStrategyData: type: object properties: direction: type: string enum: - at_level - stretch_up - downlevel description: Direction of the candidate's natural level relative to the JD level. at_level = match, stretch_up = candidate below JD, downlevel = JD below candidate. example: at_level downlevelPlan: $ref: '#/components/schemas/DownlevelPlan' generatedAt: type: string format: date-time description: ISO-8601 timestamp when the strategy was produced. Server-set. example: '2026-05-07T12:34:56.000Z' jdLevel: type: string enum: - junior - mid - senior - staff - principal - lead-manager description: Candidate or job-description career level used by the level-strategy service. example: senior naturalLevel: type: string enum: - junior - mid - senior - staff - principal - lead-manager description: Candidate or job-description career level used by the level-strategy service. example: senior recommendedFraming: type: string minLength: 1 maxLength: 800 description: 1 to 3 sentence summary the cover letter / interview prep can pull as the canonical framing line. sellSeniorPlan: $ref: '#/components/schemas/SellSeniorPlan' required: - direction - downlevelPlan - generatedAt - jdLevel - naturalLevel - recommendedFraming - sellSeniorPlan additionalProperties: false AiEditOpenResponse: type: object properties: data: type: object properties: draft: $ref: '#/components/schemas/AiEditDraft' originalContent: type: string sessionId: type: string templateKey: type: string description: PDF template hint forwarded to the preview renderer. Always "ats-optimized" today. example: ats-optimized required: - draft - originalContent - sessionId - templateKey additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response DownlevelAcceptanceCriteria: type: object properties: compFloor: type: string minLength: 1 maxLength: 280 description: Compensation threshold below which the candidate should walk away. reviewMonths: type: string minLength: 1 maxLength: 280 description: Specific 6-month (or similar) review clause text the candidate negotiates up front so a level bump is contractually anchored. scopeExpansion: type: string minLength: 1 maxLength: 280 description: Concrete scope-expansion path the candidate negotiates as part of accepting the lower level. required: - compFloor - reviewMonths - scopeExpansion additionalProperties: false UpdateApplicationStageResponse: type: object properties: data: type: object properties: applicationStage: type: string enum: - applied - callback - phone_screen - interview - offered - rejected - no_response description: Stage of the job application pipeline example: applied id: type: integer required: - applicationStage - id additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response PersonalizationPlanData: type: object properties: archetype: type: string enum: - ai_platform_llmops - agentic_automation - technical_ai_pm - ai_solutions_architect - ai_forward_deployed - ai_transformation_lead - generic_engineering - generic_product - generic_data - other description: Role archetype tag mirrored from the job match analysis (Block A) example: ai_platform_llmops cvChanges: type: array items: $ref: '#/components/schemas/CvChange' description: Exactly 5 CV changes ordered by priority (high first) generatedAt: type: string format: date-time description: ISO-8601 timestamp when the plan was produced (server-set) example: '2026-05-07T12:00:00.000Z' keywords: type: array items: type: string minLength: 1 maxLength: 80 minItems: 8 maxItems: 15 description: 8-15 ATS keywords extracted from the JD linkedinChanges: type: array items: $ref: '#/components/schemas/LinkedinChange' description: Exactly 5 LinkedIn changes ordered by priority (high first) required: - archetype - cvChanges - generatedAt - keywords - linkedinChanges additionalProperties: false EducationEntry: type: object properties: degree: type: string example: B.S. Computer Science endDate: type: - string - 'null' gpa: type: - string - 'null' highlights: type: - array - 'null' items: type: string institution: type: string example: MIT location: type: - string - 'null' startDate: type: - string - 'null' required: - degree - institution additionalProperties: false CvChange: type: object properties: currentState: type: string minLength: 1 maxLength: 400 description: One-sentence excerpt of what the CV currently has in this section priority: type: string enum: - high - medium - low description: How impactful this change is for the targeted role example: high proposedChange: type: string minLength: 1 maxLength: 400 description: Specific edit to apply, citing JD vocabulary in native tech English rationale: type: string minLength: 1 maxLength: 600 description: Why this edit closes a gap or amplifies a strength for THIS archetype section: type: string enum: - summary - experience - skills - projects - education description: Resume section the proposed change targets example: summary required: - currentState - priority - proposedChange - rationale - section additionalProperties: false LevelStrategyResponse: type: object properties: data: $ref: '#/components/schemas/LevelStrategyResponseData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response RefineDocumentResponse: type: object properties: data: type: object properties: id: type: integer documentType: type: string enum: - resume - cover-letter description: Type of PDF document to download example: resume status: type: string enum: - refining - ready description: Status of a document refinement operation example: ready refinedContent: type: string description: The refined document content (markdown) after applying user instructions required: - id - documentType - status - refinedContent additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response ApplicationResultItemResponse: type: object properties: data: $ref: '#/components/schemas/ApplicationResultData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response OutreachMessagesData: type: object properties: linkedinConnectionRequest: type: string description: LinkedIn connection request message (max 300 chars) linkedinFollowUp: type: string description: Follow-up message after connection accepted coldEmail: type: object properties: subject: type: string description: Email subject line body: type: string description: Email body text required: - subject - body additionalProperties: false description: Cold email to hiring manager suggestedContacts: type: array items: $ref: '#/components/schemas/SuggestedContact' description: Suggested contacts to reach out to byContactType: type: - object - 'null' properties: recruiter: $ref: '#/components/schemas/ContactTypeMessage' hiring_manager: allOf: - $ref: '#/components/schemas/ContactTypeMessage' - description: 'Hiring manager outreach: Hook / Proof / conversation invite' peer: allOf: - $ref: '#/components/schemas/ContactTypeMessage' - description: 'Peer / referral angle: Interest / Connection / "Would love your take"' interviewer: allOf: - $ref: '#/components/schemas/ContactTypeMessage' - description: 'Pre-interview prep: Research / Context / "Looking forward to [date]"' required: - recruiter - hiring_manager - peer - interviewer additionalProperties: false description: Per-audience outreach messages keyed by contact type. Null when AI did not emit per-audience variants. required: - linkedinConnectionRequest - linkedinFollowUp - coldEmail - suggestedContacts additionalProperties: false NegotiationScript: type: object properties: followUpResponses: type: array items: $ref: '#/components/schemas/NegotiationFollowUpResponse' minItems: 2 maxItems: 4 description: 2 to 4 follow-up replies covering common recruiter pushbacks scenario: type: string minLength: 1 maxLength: 80 description: Negotiation playbook scenario (e.g. state_expectations, signing_bonus_request). Free-form so an off-enum label never discards a valid generation. example: state_expectations script: type: string minLength: 1 maxLength: 4000 description: Ready-to-paste message in first person, 60 to 180 words situation: type: string minLength: 1 maxLength: 600 description: Short description of when the user would use this script required: - followUpResponses - scenario - script - situation additionalProperties: false QueuePositionResponse: type: object properties: data: $ref: '#/components/schemas/QueuePositionData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response SubmissionInfo: type: object properties: authPlatform: type: string description: Which platform needs auth credentials (e.g. linkedin) example: linkedin canSubmit: type: boolean description: Whether the application can be submitted to this platform hasCredentials: type: boolean description: Whether the user has stored credentials for the required platform platformType: type: string description: Detected submission platform type example: linkedin reason: type: string description: Reason submission is blocked or limited requiresAuth: type: boolean description: Whether the platform requires user authentication credentials required: - canSubmit - platformType additionalProperties: false description: Pre-flight submission requirements and credential status FormFieldsLogEntry: type: object properties: field: type: string selector: type: string value: type: string action: type: string status: type: string enum: - filled - skipped - error description: Fill status for a form field during AI-powered application example: filled required: - field - selector - value - action - status additionalProperties: false StalenessResponse: type: object properties: data: $ref: '#/components/schemas/StalenessResponseData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response LiveViewData: type: object properties: available: type: boolean description: False when the run has no browser session attached yet, or - on self-hosted Steel - when the caller is not an admin (the box admits admin sessions only). `reason` carries the cause. debuggerFullscreenUrl: type: - string - 'null' format: uri description: 'Viewer URL safe to embed in an iframe / open in a tab. Null when `available` is false. NEVER carries a credential: the self-hosted box authenticates the admin''s own session cookie.' reason: type: - string - 'null' description: Why no viewer URL could be resolved. Null when `available` is true. Never a fabricated URL - an unresolvable viewer is reported as an absence with its cause. sessionId: type: - string - 'null' description: Underlying Browserbase session id (mirrors application_result.submissionActorRunId). required: - available - debuggerFullscreenUrl - reason - sessionId additionalProperties: false AiEditDraft: type: object properties: content: type: string sections: $ref: '#/components/schemas/AiEditDraftSections' required: - content - sections additionalProperties: false ParseTailoredResumeData: type: object properties: id: type: integer certifications: type: array items: type: string education: type: array items: $ref: '#/components/schemas/ParsedTailoredResumeEducation' experience: type: array items: $ref: '#/components/schemas/ParsedTailoredResumeExperience' personalInfo: $ref: '#/components/schemas/ParsedTailoredResumePersonalInfo' skills: type: array items: type: string summary: type: - string - 'null' required: - id - certifications - education - experience - personalInfo - skills additionalProperties: false ExtractFormResponse: type: object properties: data: $ref: '#/components/schemas/ExtractFormData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response NegotiationOfferContext: type: - object - 'null' properties: company: type: string minLength: 1 maxLength: 200 description: Company name the offer is from example: Acme Corp jobTitle: type: string minLength: 1 maxLength: 200 description: Job title of the offered role example: Senior Software Engineer marketRangeCurrency: type: - string - 'null' minLength: 1 maxLength: 8 description: ISO currency code for the market range anchors. Null when no market data was available. example: USD marketRangeHigh: type: - number - 'null' description: High end of the comp-intelligence market range, when known. Null otherwise. marketRangeLow: type: - number - 'null' description: Low end of the comp-intelligence market range, when known. Null otherwise. required: - company - jobTitle - marketRangeCurrency - marketRangeHigh - marketRangeLow additionalProperties: false description: Snapshot of the offer the scripts were drafted for. Null on legacy cached payloads. ResponseMetadata: type: object properties: duration: type: number description: Request duration in milliseconds example: 150 exclusiveMinimum: 0 performance: type: object properties: dbQueries: type: integer minimum: 0 totalDbTime: type: number minimum: 0 description: Performance metrics (preview/local only) requestId: type: string description: Unique request identifier example: req_abc123 timestamp: type: string format: date-time description: ISO 8601 timestamp example: '2026-09-25T17:29:47.224Z' version: type: string description: API version example: v1 CancelResponse: type: object properties: data: $ref: '#/components/schemas/CancelResultData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response FormValuesResponse: type: object properties: data: type: object properties: updated: type: boolean required: - updated additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response PipelineStatusResponse: type: object properties: data: $ref: '#/components/schemas/PipelineStatusData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response SwitchDocumentResponseData: type: object properties: documentId: type: - integer - 'null' id: type: integer kind: type: string enum: - resume - cover_letter description: Which bound document to swap on the application result. example: resume target: type: string enum: - base - tailored - document_id description: Where to point the bound document. "base" picks the user's base resume/cover-letter; "tailored" keeps the existing tailored doc; "document_id" requires `documentId` and binds to a user-owned document by id. example: base required: - documentId - id - kind - target additionalProperties: false RefineDocumentRequest: type: object properties: documentType: type: string enum: - resume - cover-letter description: 'Which document to refine: resume or coverLetter' example: resume userInstructions: type: string minLength: 1 maxLength: 2000 description: Custom instructions for the AI to refine the document example: Emphasize my React and TypeScript experience more. Remove the reference to Python. required: - documentType - userInstructions additionalProperties: false FormValuesRequest: type: object properties: formFields: type: array items: $ref: '#/components/schemas/FormFieldValue' maxItems: 500 description: User-reviewed form field values (max 500) screeningAnswers: type: array items: $ref: '#/components/schemas/ScreeningAnswer' maxItems: 200 description: User-reviewed screening question answers (max 200) required: - formFields additionalProperties: false QueuePositionData: type: object properties: position: type: integer minimum: 0 description: 1-based rank of this row in the dispatcher's oldest-first ordering (created_at ASC) among all platform-wide rows still waiting or submitting. 1 while this row is actively processing. 0 when the row is not queued (terminal, awaiting approval, or still preparing). example: 3 aheadCount: type: integer minimum: 0 description: How many applications are ahead of this one platform-wide (position - 1). example: 2 totalWaiting: type: integer minimum: 0 description: Total rows in the apply queue right now (ready_to_submit + submitting, platform-wide). example: 12 isProcessing: type: boolean description: True when this row is already being submitted / actively processed by a worker. example: false isDone: type: boolean description: True when the row reached a terminal status (applied / skipped / error / cancelled). The client stops polling once this flips true. example: false estimatedWaitSeconds: type: - integer - 'null' minimum: 0 description: Rough seconds until this row's turn. 0 when it is next in line or already processing. Null when the row is not waiting for a slot. example: 360 required: - position - aheadCount - totalWaiting - isProcessing - isDone - estimatedWaitSeconds additionalProperties: false NegotiationResponse: type: object properties: data: $ref: '#/components/schemas/NegotiationResponseData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response FormFieldValue: type: object properties: field: type: string maxLength: 500 description: Form field label or name example: First Name value: type: string maxLength: 10000 description: Value to fill example: John status: type: string enum: - filled - skipped - error default: filled description: Fill status for this field example: filled required: - field - value additionalProperties: false AiEditAvailableScopesResponse: type: object properties: data: type: object properties: scopes: type: array items: $ref: '#/components/schemas/AiEditAvailableScope' required: - scopes additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response PrepareApplicationResponse: type: object properties: data: $ref: '#/components/schemas/PrepareApplicationData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response SingleResultData: type: object properties: applicationStage: type: - string - 'null' enum: - applied - callback - phone_screen - interview - offered - rejected - no_response - null description: Stage of the job application pipeline example: applied appliedAt: type: - string - 'null' applyMode: type: - string - 'null' enum: - copilot - auto_approve - null description: 'What the user asked for on this job, recorded at ingress and never rewritten: auto_approve (we submit) or copilot (they review first). NULL on legacy rows. Read this in preference to `status` when deciding whether a row is waiting on the user - `status` is mutated by recovery lanes.' example: auto_approve submittingStartedAt: type: - string - 'null' description: When a browser actually began this run (application_result.submitting_started_at). NULL means the row is dispatched but no browser has claimed it yet — never read preparation_status=submitting as a run having started. example: '2026-08-08T20:10:31.000Z' autoRetryStopped: type: boolean description: True when no automatic lane will ever retry this application again (submit evidence, spent retry budget, an unowned terminal error code, hourly browser cap, cancelled, an unwatched pending_review, or an orphaned job match). False whenever any lane could still claim the row or it cannot be evaluated. example: false autoRetryStoppedReason: type: - string - 'null' enum: - submit_evidence - attempts_spent - not_retryable - cancelled - needs_review - orphaned - null description: Which permanent-abandonment lane stopped this row (submit_evidence / attempts_spent / not_retryable / cancelled / needs_review / orphaned). Null when the row is not stopped OR could not be evaluated - never render null as "still going". example: null nextAutoRetryAt: type: - string - 'null' description: Earliest ISO timestamp an automatic attempt can re-claim this row, from the hourly stuck-sweep selection rounded up to the next cron tick. A floor, not a guarantee. Null means we are not naming a time - NOT that no retry exists. example: null updatedAt: type: - string - 'null' submitEvidenceTier: type: string enum: - other_side_confirmed - our_click_only - no_submit_evidence description: 'Whose observation backs this row: other_side_confirmed (the employer produced a receipt), our_click_only (we clicked Submit but could not read a receipt - an absence, never proof it landed), or no_submit_evidence (we never clicked).' example: no_submit_evidence employerReceiptConfirmed: type: boolean description: Receipt proof from the employer exists for this application. Screenshot or confirmation-page proof is represented separately in landingProofs. Outranks our own status. example: false landingProofs: type: array items: type: string enum: - receipt - screenshot description: Who authored the evidence that this application reached the employer. `receipt` = the employer emailed a confirmation linked to this row. `screenshot` = a review of the stored post-submit screenshot read the employer's OWN confirmation page. Both are the other side's answer and both count as a proven landing; a row may hold either or both. example: screenshot description: 'Employer-authored proof this application landed: `receipt` (their confirmation email, linked) and/or `screenshot` (a review read their own confirmation page). Empty = no such proof, which is NOT a failure.' example: - screenshot statusDisplay: anyOf: - type: object properties: label: type: string minLength: 1 description: Legacy English badge text for rolling compatibility. V2 clients localize from code and params instead of rendering this field. example: Trying again shortly · pass 3 of 4 noCreditUsed: type: boolean description: True only when no billable AI or browser work ran for this row (the skipped short-circuits). An errored apply is never "free". example: false pendingRetryAt: type: - string - 'null' format: date-time description: Earliest ISO timestamp an automatic attempt can re-claim this row, echoed only with matching V2 scheduledAttempt params. Null means we are not naming a time, never that no retry exists. example: null tone: type: string enum: - success - warning - info - destructive - settled - neutral - muted description: Platform-agnostic colour verdict for a derived application status badge. Web maps it to a Tailwind bg-* class, mobile to a theme hex. Never a class name on the wire. example: info code: type: string enum: - queued - preparing - queued_to_apply - waiting_for_browser - submitting - action_needed - waiting_for_review - applied - applied_confirming_landing - employer_receipt_confirmed - sent_no_receipt_read - submitted_verifying - already_applied - retrying_our_hiccup - retrying_soon - employer_rejected_retrying - failed_retrying - resumes_when_funded - signing_in - paused - resuming - resume_required - not_through - no_form - not_ready_to_send - not_submitted - linkedin_easy_apply - job_unavailable - aggregator_skipped - result_submitted - result_submitted_awaiting_receipt - cancelled - result_error - result_preparing - result_pending_approval - result_ready_to_submit - result_skipped - stopped_generic - stopped_submit_evidence - stopped_attempts_spent - stopped_not_retryable - stopped_cancelled - stopped_needs_review - stopped_orphaned - stopped_our_click_only - unknown description: Stable semantic code for a derived application status display. Clients localize this code and use the legacy label only for rolling compatibility. example: queued_to_apply params: type: object properties: attemptsMade: type: - integer - 'null' exclusiveMinimum: 0 retryBudget: type: - object - 'null' properties: remaining: type: integer minimum: 0 total: type: integer exclusiveMinimum: 0 required: - remaining - total additionalProperties: false scheduledAttempt: type: - object - 'null' properties: current: type: integer exclusiveMinimum: 0 total: type: integer exclusiveMinimum: 0 required: - current - total additionalProperties: false required: - attemptsMade - retryBudget - scheduledAttempt additionalProperties: false schemaVersion: type: number enum: - 2 required: - label - noCreditUsed - pendingRetryAt - tone - code - params - schemaVersion additionalProperties: false - type: object properties: label: type: string minLength: 1 description: Legacy English badge text for rolling compatibility. V2 clients localize from code and params instead of rendering this field. example: Trying again shortly · pass 3 of 4 noCreditUsed: type: boolean description: True only when no billable AI or browser work ran for this row (the skipped short-circuits). An errored apply is never "free". example: false pendingRetryAt: type: - string - 'null' format: date-time description: Earliest ISO timestamp an automatic attempt can re-claim this row, echoed only with matching V2 scheduledAttempt params. Null means we are not naming a time, never that no retry exists. example: null tone: type: string enum: - success - warning - info - destructive - settled - neutral - muted description: Platform-agnostic colour verdict for a derived application status badge. Web maps it to a Tailwind bg-* class, mobile to a theme hex. Never a class name on the wire. example: info required: - label - noCreditUsed - pendingRetryAt - tone additionalProperties: false - {} description: The server-derived status verdict. V2 clients localize its stable code and typed params, then map the semantic tone to platform tokens. The English label remains only for rolling compatibility. Null means the row has no apply-pipeline state, so clients fall back to the listing status. example: null browserbaseDebugUrl: type: - string - 'null' browserbaseSessionId: type: - string - 'null' browserbaseSessionUrl: type: - string - 'null' city: type: - string - 'null' description: Parsed city from the parent job match, when available. company: type: - string - 'null' companyLogoUrl: type: - string - 'null' companyDomain: type: - string - 'null' description: Trusted company-intel domain (company.domain) from the parent job match for the card logo fallback. Null when the row has no linked company record or the company has no domain. example: acme.com country: type: - string - 'null' description: Canonical country code from the parent job match. contentLocked: type: boolean description: True when the generated content on this row is truncated because it was prepared without a paid plan. example: true revealPreviewChars: type: integer description: Character budget of the preview when contentLocked is true. Lets the client size the fade without hardcoding the server constant. example: 220 coverLetterContent: type: - string - 'null' coverLetterDocId: type: - integer - 'null' coverLetterPdfR2Key: type: - string - 'null' createdAt: type: - string - 'null' documentsOutdatedAt: type: - string - 'null' errorCode: type: - string - 'null' enum: - access_blocked - agent_stuck - agent_stuck_dom_unchanged - agent_stuck_no_cdp_progress - agent_stuck_no_progress_after_warmup - aggregator_preflight - aggregator_redirect - already_applied - apply_button_not_found - ashby_autofill_banner_failed - auth_wall_blocking - auth_wall_detected - account_door_unsupported - account_created_reapply - auto_retries_exhausted - browser_session_lost - browser_timeout - captcha_blocked - captcha_requires_human - captcha_unsolvable - cloudflare_challenge - credits_exhausted - d1_unavailable_at_claim - daily_spend_cap - auth_required - do_reset - duplicate - duplicate_fence_held - emailed_code_never_arrived - element_stale - employer_eligibility_knockout - false_positive_blocked - field_unfillable - form_not_found - hourly_browser_cap - html_content_guard - insufficient_tokens - invalid_apply_url - job_closed - job_not_found - job_removed - job_unsaved - kill_switch_active - manual_test_no_run - max_steps_reached - multi_step_stalled - network_error - no_form_present - no_resume_uploaded - oauth_session_expired - oauth_wall_detected - page_navigated_away - page_too_complex - page_unreachable - page_unreadable - post_submit_unconfirmed - preparation_incomplete - proxy_exhausted - proxy_tunnel_dead - quota_exhausted - rate_limited - redirect_blocked - requires_human_review - service_unavailable - session_expired - session_stale - spam_flagged - stuck_in_loop - submission_error - submit_deadline_exhausted - submit_did_not_take - submit_transport_failed - submit_validation_rejected - submit_withheld_form_refused - two_factor_required - universal_fill_zero_match - validation_error - worker_died - wrong_landing_page - unknown - null description: Classification of submission failure for strategy-aware retry example: network_error errorMessage: type: - string - 'null' failurePhase: type: - string - 'null' enum: - prepare - navigate - login - fill - submit - verify - aggregate - unknown - null description: Coarse-grained phase where a submission failure occurred example: submit id: type: integer improvementSuggestions: type: - array - 'null' items: type: string jobListingId: type: - integer - 'null' jobMatchId: type: - integer - 'null' jobTitle: type: - string - 'null' jobType: type: - string - 'null' description: Job type (full_time, contract, etc.) from the parent job match. jobUrl: type: string location: type: - string - 'null' description: Free-text location string from the parent job match. matchConfidence: type: - integer - 'null' outreachMessages: type: - string - 'null' postedAt: type: - string - 'null' description: Original posting date from the parent job match. salary: type: - string - 'null' description: Salary string from the parent job match. source: type: - string - 'null' description: Aggregator / source of the parent job match (greenhouse, lever, linkedin, etc.). workArrangement: type: - string - 'null' description: Canonical work-arrangement (remote_global / remote_country / remote_region / hybrid / onsite / unknown) from the parent job match. phase: type: - string - 'null' enum: - processing - idle - paused - null description: Server-truth lifecycle phase for a single auto-apply run row. `processing` = worker actively running a step. `idle` = between steps, waiting for next pickup. `paused` = rate-limit backoff, captcha wait, or explicit user pause. example: processing preparationStatus: type: string enum: - pending - preparing - ready - submitting - submitted - failed - cancelled description: Status of application preparation (resume tailoring + cover letter) example: pending retryCount: type: integer minimum: 0 qualityGateAction: type: - string - 'null' enum: - approved - flagged - blocked - null description: 'Outcome of the quality gate check: approved (proceed), flagged (needs review), blocked (rejected)' example: approved screenshotAfterUrl: type: - string - 'null' screenshotBeforeUrl: type: - string - 'null' screenshotKey: type: - string - 'null' sessionLiveViewUrl: type: - string - 'null' format: uri status: type: string enum: - pending - pending_review - ready_to_submit - applied - applied_unconfirmed - skipped - error - cancelled description: Status of an individual application result example: pending submissionPlatform: type: - string - 'null' submittedVia: type: - string - 'null' enum: - direct_api - form_post - linkedin_easy_apply - indeed_apply - glassdoor_apply - ziprecruiter_apply - authenticated_browser - workday_navigator - ai_browser_agent - email_fallback - null description: Strategy used to submit a job application example: direct_api tailoredResumeContent: type: - string - 'null' tailoredResumeDocId: type: - integer - 'null' tailoredResumePdfR2Key: type: - string - 'null' tailoredResumeStructured: $ref: '#/components/schemas/AIResumeData' tokensRefunded: type: - integer - 'null' refundReason: type: - string - 'null' enum: - job_closed - service_unavailable - credits_exhausted - session_expired - session_stale - infra_error - null description: Why a token reservation was refunded in full after a non-user-fault submission failure example: job_closed legitimacyTier: type: - string - 'null' enum: - high_confidence - proceed_with_caution - suspicious - null description: Deterministic posting-legitimacy verdict from the parent job match. Null when not yet evaluated. example: proceed_with_caution legitimacySignals: anyOf: - type: string - {} description: Serialized LegitimacySignals payload (score + signals[] + tier) from the parent job match. Null when not yet evaluated. freshnessStatus: type: - string - 'null' enum: - fresh - aging - stale - unknown - null description: Posting age bucket (fresh / aging / stale / unknown) from the scraped_job snapshot. example: fresh repostedCount: type: - integer - 'null' minimum: 0 description: Number of prior live scraped_job rows for this URL family. 0 when no repost history. example: 0 lastRepostDate: type: - string - 'null' description: posted_date of the most-recent prior repost. Null when no prior posting exists. example: '2026-03-04' linkedinApplyMethod: type: - string - 'null' enum: - easy_apply - offsite - unknown - null description: Resolved LinkedIn apply target from the parent job match. `offsite` → applies on a company ATS (suppress "Reconnect LinkedIn" copy); `easy_apply` → in-platform LinkedIn Easy Apply; `unknown` → not yet resolved / not a LinkedIn posting. Null when the row has no linked job match. example: offsite submissionInfo: $ref: '#/components/schemas/SubmissionInfo' alreadyAppliedProof: type: - object - 'null' properties: notice: type: string minLength: 1 maxLength: 500 pageUrl: type: - string - 'null' maxLength: 2048 screenshotUrl: type: - string - 'null' maxLength: 2048 seenAt: type: string minLength: 1 source: type: string enum: - post_submit_page - self_judge - vision_page_text required: - notice - pageUrl - screenshotUrl - seenAt - source description: 'Evidence behind an already_applied verdict: the employer page''s own notice, its URL and the screenshot of that page. Null when the verdict has no employer-page proof. Detail projection only.' committedFields: type: - array - 'null' items: type: object properties: attempt: type: integer minimum: 1 enteredValue: type: - string - 'null' maxLength: 512 label: type: string minLength: 1 maxLength: 200 lane: type: string minLength: 1 maxLength: 160 phase: type: string minLength: 1 maxLength: 64 provenance: type: string enum: - profile - answer_context - document - derived - generated - guessed - unsourced description: Where the value committed into an employer form came from example: profile source: type: string minLength: 1 maxLength: 64 value: type: - string - 'null' maxLength: 512 valueShape: type: string minLength: 1 maxLength: 32 verified: type: boolean required: - attempt - label - phase - provenance - value - valueShape - verified additionalProperties: false maxItems: 128 description: Per-field record of the values committed into the employer form, with raw value, provenance and a read-back verified flag. A read-back of our own write - never evidence an application landed. Null on historical rows. identityCommitted: type: - object - 'null' properties: email: type: - boolean - 'null' firstName: type: - boolean - 'null' lastName: type: - boolean - 'null' required: - email - firstName - lastName additionalProperties: false description: Which of firstName/lastName/email read back present at the submit click. A read-back of our own write - MUST NEVER be used to score whether an application landed. Per-member null means UNOBSERVED, never false. Null on historical rows. phaseTimings: type: - object - 'null' properties: aggregate: type: integer minimum: 0 captchaMs: type: integer minimum: 0 currentPhase: type: string enum: - prepare - navigate - login - fill - submit - verify - aggregate - unknown description: Coarse-grained phase where a submission failure occurred example: submit currentPhaseMs: type: integer minimum: 0 employerMailWaitMs: type: integer minimum: 0 fill: type: integer minimum: 0 fillPerAttempt: type: array items: type: integer minimum: 0 login: type: integer minimum: 0 msToSubmitPress: type: integer minimum: 0 navigate: type: integer minimum: 0 prepare: type: integer minimum: 0 prepareStep: type: string maxLength: 160 slowestSteps: type: array items: type: object properties: ms: type: integer minimum: 0 ourMs: type: integer minimum: 0 step: type: string maxLength: 160 waitedOnEmployerMailMs: type: integer minimum: 0 required: - ms - step additionalProperties: false submit: type: integer minimum: 0 submitPerAttempt: type: array items: type: integer minimum: 0 totalMs: type: integer minimum: 0 unaccountedMs: type: integer minimum: 0 unknown: type: integer minimum: 0 verify: type: integer minimum: 0 required: - totalMs - unaccountedMs additionalProperties: false description: Per-phase wall clock for the run, keyed on the failure-phase enum, plus totalMs, captchaMs and unaccountedMs. An absent phase key is UNOBSERVED, never zero. Null on historical rows. formFieldsLog: type: - string - 'null' screeningAnswers: type: - string - 'null' submissionActorRunId: type: - string - 'null' submissionAttempts: type: - array - 'null' items: anyOf: - type: object properties: detail: type: string durationMs: type: integer minimum: 0 error: type: string replayUrl: type: string format: uri screenshotKeys: type: array items: type: string skippedOptionalFieldCount: type: integer minimum: 0 strategy: type: string enum: - direct_api - form_post - linkedin_easy_apply - indeed_apply - glassdoor_apply - ziprecruiter_apply - authenticated_browser - workday_navigator - ai_browser_agent - email_fallback description: Strategy used to submit a job application example: direct_api success: type: boolean targetUrl: type: string timestamp: type: string required: - strategy - success - timestamp additionalProperties: false - type: object properties: detail: type: string durationMs: type: integer minimum: 0 error: type: string phase: type: string enum: - preparation - submission - dispatcher - queue_consumer - inline_fallback - orphan_recovery - unknown strategy: type: string success: type: boolean timestamp: type: string required: - detail - phase - strategy - success - timestamp submitObservedApplicationId: type: - string - 'null' submitObservedOk: type: - integer - 'null' submissionVerified: type: - integer - 'null' landingConfidence: type: - integer - 'null' minimum: 0 maximum: 100 queuePosition: type: - integer - 'null' description: 1-based rank among all ready_to_submit rows (oldest-enqueued first). Null unless the row is waiting for a slot. example: 3 exclusiveMinimum: 0 queueTotal: type: - integer - 'null' minimum: 0 description: Count of every ready_to_submit + submitting row platform-wide. Null unless the row is waiting for a slot. example: 12 queueEtaMinutes: type: - integer - 'null' minimum: 0 description: Rough minutes until this row's turn. 0 when it is next / a slot is free. Null unless the row is waiting for a slot. example: 6 required: - applicationStage - appliedAt - autoRetryStopped - autoRetryStoppedReason - nextAutoRetryAt - updatedAt - submitEvidenceTier - employerReceiptConfirmed - statusDisplay - city - company - companyLogoUrl - country - coverLetterContent - coverLetterDocId - coverLetterPdfR2Key - createdAt - documentsOutdatedAt - errorCode - errorMessage - id - improvementSuggestions - jobListingId - jobMatchId - jobTitle - jobType - jobUrl - location - matchConfidence - outreachMessages - postedAt - salary - source - workArrangement - phase - preparationStatus - retryCount - qualityGateAction - screenshotAfterUrl - screenshotBeforeUrl - screenshotKey - sessionLiveViewUrl - status - submissionPlatform - submittedVia - tailoredResumeContent - tailoredResumeDocId - tailoredResumePdfR2Key - tokensRefunded - refundReason - submissionInfo - formFieldsLog - screeningAnswers - submissionActorRunId - submissionAttempts - submitObservedApplicationId - submitObservedOk - submissionVerified - landingConfidence additionalProperties: false ApplicationResultData: type: object properties: applicationStage: type: - string - 'null' enum: - applied - callback - phone_screen - interview - offered - rejected - no_response - null description: Stage of the job application pipeline example: applied appliedAt: type: - string - 'null' applyMode: type: - string - 'null' enum: - copilot - auto_approve - null description: 'What the user asked for on this job, recorded at ingress and never rewritten: auto_approve (we submit) or copilot (they review first). NULL on legacy rows. Read this in preference to `status` when deciding whether a row is waiting on the user - `status` is mutated by recovery lanes.' example: auto_approve submittingStartedAt: type: - string - 'null' description: When a browser actually began this run (application_result.submitting_started_at). NULL means the row is dispatched but no browser has claimed it yet — never read preparation_status=submitting as a run having started. example: '2026-08-08T20:10:31.000Z' autoRetryStopped: type: boolean description: True when no automatic lane will ever retry this application again (submit evidence, spent retry budget, an unowned terminal error code, hourly browser cap, cancelled, an unwatched pending_review, or an orphaned job match). False whenever any lane could still claim the row or it cannot be evaluated. example: false autoRetryStoppedReason: type: - string - 'null' enum: - submit_evidence - attempts_spent - not_retryable - cancelled - needs_review - orphaned - null description: Which permanent-abandonment lane stopped this row (submit_evidence / attempts_spent / not_retryable / cancelled / needs_review / orphaned). Null when the row is not stopped OR could not be evaluated - never render null as "still going". example: null nextAutoRetryAt: type: - string - 'null' description: Earliest ISO timestamp an automatic attempt can re-claim this row, from the hourly stuck-sweep selection rounded up to the next cron tick. A floor, not a guarantee. Null means we are not naming a time - NOT that no retry exists. example: null updatedAt: type: - string - 'null' submitEvidenceTier: type: string enum: - other_side_confirmed - our_click_only - no_submit_evidence description: 'Whose observation backs this row: other_side_confirmed (the employer produced a receipt), our_click_only (we clicked Submit but could not read a receipt - an absence, never proof it landed), or no_submit_evidence (we never clicked).' example: no_submit_evidence employerReceiptConfirmed: type: boolean description: Receipt proof from the employer exists for this application. Screenshot or confirmation-page proof is represented separately in landingProofs. Outranks our own status. example: false landingProofs: type: array items: type: string enum: - receipt - screenshot description: Who authored the evidence that this application reached the employer. `receipt` = the employer emailed a confirmation linked to this row. `screenshot` = a review of the stored post-submit screenshot read the employer's OWN confirmation page. Both are the other side's answer and both count as a proven landing; a row may hold either or both. example: screenshot description: 'Employer-authored proof this application landed: `receipt` (their confirmation email, linked) and/or `screenshot` (a review read their own confirmation page). Empty = no such proof, which is NOT a failure.' example: - screenshot statusDisplay: anyOf: - type: object properties: label: type: string minLength: 1 description: Legacy English badge text for rolling compatibility. V2 clients localize from code and params instead of rendering this field. example: Trying again shortly · pass 3 of 4 noCreditUsed: type: boolean description: True only when no billable AI or browser work ran for this row (the skipped short-circuits). An errored apply is never "free". example: false pendingRetryAt: type: - string - 'null' format: date-time description: Earliest ISO timestamp an automatic attempt can re-claim this row, echoed only with matching V2 scheduledAttempt params. Null means we are not naming a time, never that no retry exists. example: null tone: type: string enum: - success - warning - info - destructive - settled - neutral - muted description: Platform-agnostic colour verdict for a derived application status badge. Web maps it to a Tailwind bg-* class, mobile to a theme hex. Never a class name on the wire. example: info code: type: string enum: - queued - preparing - queued_to_apply - waiting_for_browser - submitting - action_needed - waiting_for_review - applied - applied_confirming_landing - employer_receipt_confirmed - sent_no_receipt_read - submitted_verifying - already_applied - retrying_our_hiccup - retrying_soon - employer_rejected_retrying - failed_retrying - resumes_when_funded - signing_in - paused - resuming - resume_required - not_through - no_form - not_ready_to_send - not_submitted - linkedin_easy_apply - job_unavailable - aggregator_skipped - result_submitted - result_submitted_awaiting_receipt - cancelled - result_error - result_preparing - result_pending_approval - result_ready_to_submit - result_skipped - stopped_generic - stopped_submit_evidence - stopped_attempts_spent - stopped_not_retryable - stopped_cancelled - stopped_needs_review - stopped_orphaned - stopped_our_click_only - unknown description: Stable semantic code for a derived application status display. Clients localize this code and use the legacy label only for rolling compatibility. example: queued_to_apply params: type: object properties: attemptsMade: type: - integer - 'null' exclusiveMinimum: 0 retryBudget: type: - object - 'null' properties: remaining: type: integer minimum: 0 total: type: integer exclusiveMinimum: 0 required: - remaining - total additionalProperties: false scheduledAttempt: type: - object - 'null' properties: current: type: integer exclusiveMinimum: 0 total: type: integer exclusiveMinimum: 0 required: - current - total additionalProperties: false required: - attemptsMade - retryBudget - scheduledAttempt additionalProperties: false schemaVersion: type: number enum: - 2 required: - label - noCreditUsed - pendingRetryAt - tone - code - params - schemaVersion additionalProperties: false - type: object properties: label: type: string minLength: 1 description: Legacy English badge text for rolling compatibility. V2 clients localize from code and params instead of rendering this field. example: Trying again shortly · pass 3 of 4 noCreditUsed: type: boolean description: True only when no billable AI or browser work ran for this row (the skipped short-circuits). An errored apply is never "free". example: false pendingRetryAt: type: - string - 'null' format: date-time description: Earliest ISO timestamp an automatic attempt can re-claim this row, echoed only with matching V2 scheduledAttempt params. Null means we are not naming a time, never that no retry exists. example: null tone: type: string enum: - success - warning - info - destructive - settled - neutral - muted description: Platform-agnostic colour verdict for a derived application status badge. Web maps it to a Tailwind bg-* class, mobile to a theme hex. Never a class name on the wire. example: info required: - label - noCreditUsed - pendingRetryAt - tone additionalProperties: false - {} description: The server-derived status verdict. V2 clients localize its stable code and typed params, then map the semantic tone to platform tokens. The English label remains only for rolling compatibility. Null means the row has no apply-pipeline state, so clients fall back to the listing status. example: null browserbaseDebugUrl: type: - string - 'null' browserbaseSessionId: type: - string - 'null' browserbaseSessionUrl: type: - string - 'null' city: type: - string - 'null' description: Parsed city from the parent job match, when available. company: type: - string - 'null' companyLogoUrl: type: - string - 'null' companyDomain: type: - string - 'null' description: Trusted company-intel domain (company.domain) from the parent job match for the card logo fallback. Null when the row has no linked company record or the company has no domain. example: acme.com country: type: - string - 'null' description: Canonical country code from the parent job match. contentLocked: type: boolean description: True when the generated content on this row is truncated because it was prepared without a paid plan. example: true revealPreviewChars: type: integer description: Character budget of the preview when contentLocked is true. Lets the client size the fade without hardcoding the server constant. example: 220 coverLetterContent: type: - string - 'null' coverLetterDocId: type: - integer - 'null' coverLetterPdfR2Key: type: - string - 'null' createdAt: type: - string - 'null' documentsOutdatedAt: type: - string - 'null' errorCode: type: - string - 'null' enum: - access_blocked - agent_stuck - agent_stuck_dom_unchanged - agent_stuck_no_cdp_progress - agent_stuck_no_progress_after_warmup - aggregator_preflight - aggregator_redirect - already_applied - apply_button_not_found - ashby_autofill_banner_failed - auth_wall_blocking - auth_wall_detected - account_door_unsupported - account_created_reapply - auto_retries_exhausted - browser_session_lost - browser_timeout - captcha_blocked - captcha_requires_human - captcha_unsolvable - cloudflare_challenge - credits_exhausted - d1_unavailable_at_claim - daily_spend_cap - auth_required - do_reset - duplicate - duplicate_fence_held - emailed_code_never_arrived - element_stale - employer_eligibility_knockout - false_positive_blocked - field_unfillable - form_not_found - hourly_browser_cap - html_content_guard - insufficient_tokens - invalid_apply_url - job_closed - job_not_found - job_removed - job_unsaved - kill_switch_active - manual_test_no_run - max_steps_reached - multi_step_stalled - network_error - no_form_present - no_resume_uploaded - oauth_session_expired - oauth_wall_detected - page_navigated_away - page_too_complex - page_unreachable - page_unreadable - post_submit_unconfirmed - preparation_incomplete - proxy_exhausted - proxy_tunnel_dead - quota_exhausted - rate_limited - redirect_blocked - requires_human_review - service_unavailable - session_expired - session_stale - spam_flagged - stuck_in_loop - submission_error - submit_deadline_exhausted - submit_did_not_take - submit_transport_failed - submit_validation_rejected - submit_withheld_form_refused - two_factor_required - universal_fill_zero_match - validation_error - worker_died - wrong_landing_page - unknown - null description: Classification of submission failure for strategy-aware retry example: network_error errorMessage: type: - string - 'null' failurePhase: type: - string - 'null' enum: - prepare - navigate - login - fill - submit - verify - aggregate - unknown - null description: Coarse-grained phase where a submission failure occurred example: submit id: type: integer improvementSuggestions: type: - array - 'null' items: type: string jobListingId: type: - integer - 'null' jobMatchId: type: - integer - 'null' jobTitle: type: - string - 'null' jobType: type: - string - 'null' description: Job type (full_time, contract, etc.) from the parent job match. jobUrl: type: string location: type: - string - 'null' description: Free-text location string from the parent job match. matchConfidence: type: - integer - 'null' outreachMessages: type: - string - 'null' postedAt: type: - string - 'null' description: Original posting date from the parent job match. salary: type: - string - 'null' description: Salary string from the parent job match. source: type: - string - 'null' description: Aggregator / source of the parent job match (greenhouse, lever, linkedin, etc.). workArrangement: type: - string - 'null' description: Canonical work-arrangement (remote_global / remote_country / remote_region / hybrid / onsite / unknown) from the parent job match. phase: type: - string - 'null' enum: - processing - idle - paused - null description: Server-truth lifecycle phase for a single auto-apply run row. `processing` = worker actively running a step. `idle` = between steps, waiting for next pickup. `paused` = rate-limit backoff, captcha wait, or explicit user pause. example: processing preparationStatus: type: string enum: - pending - preparing - ready - submitting - submitted - failed - cancelled description: Status of application preparation (resume tailoring + cover letter) example: pending retryCount: type: integer minimum: 0 qualityGateAction: type: - string - 'null' enum: - approved - flagged - blocked - null description: 'Outcome of the quality gate check: approved (proceed), flagged (needs review), blocked (rejected)' example: approved screenshotAfterUrl: type: - string - 'null' screenshotBeforeUrl: type: - string - 'null' screenshotKey: type: - string - 'null' sessionLiveViewUrl: type: - string - 'null' format: uri status: type: string enum: - pending - pending_review - ready_to_submit - applied - applied_unconfirmed - skipped - error - cancelled description: Status of an individual application result example: pending submissionPlatform: type: - string - 'null' submittedVia: type: - string - 'null' enum: - direct_api - form_post - linkedin_easy_apply - indeed_apply - glassdoor_apply - ziprecruiter_apply - authenticated_browser - workday_navigator - ai_browser_agent - email_fallback - null description: Strategy used to submit a job application example: direct_api tailoredResumeContent: type: - string - 'null' tailoredResumeDocId: type: - integer - 'null' tailoredResumePdfR2Key: type: - string - 'null' tailoredResumeStructured: $ref: '#/components/schemas/AIResumeData' tokensRefunded: type: - integer - 'null' refundReason: type: - string - 'null' enum: - job_closed - service_unavailable - credits_exhausted - session_expired - session_stale - infra_error - null description: Why a token reservation was refunded in full after a non-user-fault submission failure example: job_closed legitimacyTier: type: - string - 'null' enum: - high_confidence - proceed_with_caution - suspicious - null description: Deterministic posting-legitimacy verdict from the parent job match. Null when not yet evaluated. example: proceed_with_caution legitimacySignals: anyOf: - type: string - {} description: Serialized LegitimacySignals payload (score + signals[] + tier) from the parent job match. Null when not yet evaluated. freshnessStatus: type: - string - 'null' enum: - fresh - aging - stale - unknown - null description: Posting age bucket (fresh / aging / stale / unknown) from the scraped_job snapshot. example: fresh repostedCount: type: - integer - 'null' minimum: 0 description: Number of prior live scraped_job rows for this URL family. 0 when no repost history. example: 0 lastRepostDate: type: - string - 'null' description: posted_date of the most-recent prior repost. Null when no prior posting exists. example: '2026-03-04' linkedinApplyMethod: type: - string - 'null' enum: - easy_apply - offsite - unknown - null description: Resolved LinkedIn apply target from the parent job match. `offsite` → applies on a company ATS (suppress "Reconnect LinkedIn" copy); `easy_apply` → in-platform LinkedIn Easy Apply; `unknown` → not yet resolved / not a LinkedIn posting. Null when the row has no linked job match. example: offsite submissionInfo: $ref: '#/components/schemas/SubmissionInfo' required: - applicationStage - appliedAt - autoRetryStopped - autoRetryStoppedReason - nextAutoRetryAt - updatedAt - submitEvidenceTier - employerReceiptConfirmed - statusDisplay - city - company - companyLogoUrl - country - coverLetterContent - coverLetterDocId - coverLetterPdfR2Key - createdAt - documentsOutdatedAt - errorCode - errorMessage - id - improvementSuggestions - jobListingId - jobMatchId - jobTitle - jobType - jobUrl - location - matchConfidence - outreachMessages - postedAt - salary - source - workArrangement - phase - preparationStatus - retryCount - qualityGateAction - screenshotAfterUrl - screenshotBeforeUrl - screenshotKey - sessionLiveViewUrl - status - submissionPlatform - submittedVia - tailoredResumeContent - tailoredResumeDocId - tailoredResumePdfR2Key - tokensRefunded - refundReason additionalProperties: false ScreeningAnswer: type: object properties: question: type: string maxLength: 2000 description: Screening question text answer: type: string maxLength: 10000 description: Proposed answer required: - question - answer additionalProperties: false ScreenshotInfoResponse: type: object properties: data: $ref: '#/components/schemas/ScreenshotInfoData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response NegotiateRegenerateRequest: type: object properties: force: type: boolean default: false description: Bypass the offer-stage gate and bust the KV cache to force a fresh AI generation example: false additionalProperties: false NegotiationResponseData: type: object properties: cached: type: boolean description: True when the response was served from KV cache or the persisted column example: false status: type: string enum: - idle - generating - completed - failed description: 'Generation lifecycle status: `completed` on success, `failed` when the last run failed (manual Retry)' example: completed generatedAt: type: - string - 'null' format: date-time description: ISO-8601 timestamp when the scripts were generated. Null on legacy cached payloads. example: '2026-05-07T12:34:56.000Z' offerContext: $ref: '#/components/schemas/NegotiationOfferContext' scripts: type: array items: $ref: '#/components/schemas/NegotiationScript' maxItems: 5 description: 0 to 5 offer-specific negotiation scripts (empty when status is `failed`) required: - cached - status - generatedAt - offerContext - scripts additionalProperties: false ExtractFormScreeningAnswer: type: object properties: question: type: string maxLength: 2000 answer: type: string maxLength: 10000 confidence: type: number required: - question - answer - confidence additionalProperties: false ParseTailoredResumeResponse: type: object properties: data: $ref: '#/components/schemas/ParseTailoredResumeData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response ParsedTailoredResumeExperience: type: object properties: bullets: type: array items: type: string company: type: string current: type: - boolean - 'null' endDate: type: - string - 'null' location: type: - string - 'null' startDate: type: string title: type: string required: - bullets - company - startDate - title additionalProperties: false PipelineStatusData: type: object properties: totalWaiting: type: integer minimum: 0 description: Platform-wide apply queue depth (every ready_to_submit + submitting row). example: 12 mine: type: integer minimum: 0 description: How many of the caller's own rows are waiting for a slot or actively submitting. example: 2 processing: type: integer minimum: 0 description: How many of the caller's rows are actively being submitted right now (subset of `mine`). example: 1 position: type: integer minimum: 0 description: Frontmost 1-based platform-wide rank of any of the caller's active rows. 1 when one is already processing; the real rank of the caller's oldest waiting row otherwise; 0 when the caller has nothing in the queue. example: 3 isActive: type: boolean description: True when the caller has at least one row in the apply queue right now. example: true required: - totalWaiting - mine - processing - position - isActive additionalProperties: false GenerateOutreachResponse: type: object properties: data: $ref: '#/components/schemas/OutreachMessagesData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response AtsCredentialSummary: type: object properties: accountStatus: type: string enum: - pending - created - verified - failed description: Lifecycle of an AI-Applyd-created ATS candidate account example: verified id: type: integer description: Credential row id example: 1 exclusiveMinimum: 0 loginUrl: type: - string - 'null' description: ATS account login URL example: https://company.wd1.myworkdayjobs.com platform: type: string description: ATS provider example: workday username: type: string description: Account username (the relay alias) example: jane-abc123@relay.example required: - accountStatus - id - loginUrl - platform - username additionalProperties: false LevelStrategyRequest: type: object properties: archetype: type: string enum: - ai_platform_llmops - agentic_automation - technical_ai_pm - ai_solutions_architect - ai_forward_deployed - ai_transformation_lead - generic_engineering - generic_product - generic_data - other description: Optional archetype hint from Block A of the structured evaluator. example: ai_platform_llmops force: type: boolean default: false description: Bust the KV cache and force a fresh AI generation. example: false jdLevel: type: string enum: - junior - mid - senior - staff - principal - lead-manager description: Detected level of the job description. example: senior userLevel: type: string enum: - junior - mid - senior - staff - principal - lead-manager description: Candidate's natural career level. example: senior required: - jdLevel - userLevel additionalProperties: false AiEditFinalizeRequest: type: object properties: sessionId: type: string minLength: 1 maxLength: 64 required: - sessionId additionalProperties: false ApplicationResultListResponse: type: object properties: data: type: object properties: items: type: array items: $ref: '#/components/schemas/ApplicationResultData' pagination: type: object properties: hasNext: type: boolean hasPrev: type: boolean limit: type: integer exclusiveMinimum: 0 page: type: integer exclusiveMinimum: 0 totalCount: type: integer minimum: 0 totalPages: type: integer minimum: 0 required: - hasNext - hasPrev - limit - page - totalCount - totalPages additionalProperties: false staleCount: type: integer minimum: 0 description: Count of this user's pending_review applications older than the stale window (7d). Drives the FE bulk-approve nudge. example: 0 required: - items - pagination - staleCount additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response PrepareApplicationData: type: object properties: changesApplied: type: array items: type: string coverLetterContent: type: string id: type: integer keyThemes: type: array items: type: string keywordsAdded: type: array items: type: string preparationStatus: type: string enum: - pending - preparing - ready - submitting - submitted - failed - cancelled description: Status of application preparation (resume tailoring + cover letter) example: pending preparedUnderFreeWatch: type: boolean runStartedAt: type: string format: date-time tailoredResumeContent: type: string required: - id - preparationStatus - runStartedAt additionalProperties: false BulkApproveRequest: type: object properties: resultIds: type: array items: type: string minLength: 1 minItems: 1 maxItems: 25 description: Result IDs to approve in this batch (1 to 25). String-encoded numeric IDs matching the single-row endpoint's URL param shape. Each is approved server-side independently; per-row failures do not abort the batch. example: - '101' - '102' - '103' required: - resultIds additionalProperties: false PersonalizationPlanRequest: type: object properties: jobMatchId: type: integer description: job_matches.id the plan is scoped to example: 1 exclusiveMinimum: 0 required: - jobMatchId additionalProperties: false ExtractFormData: type: object properties: formFields: type: array items: $ref: '#/components/schemas/ExtractFormField' screeningAnswers: type: array items: $ref: '#/components/schemas/ExtractFormScreeningAnswer' required: - formFields - screeningAnswers additionalProperties: false RePrepareResponseData: type: object properties: id: type: integer stepsRun: type: array items: type: string enum: - quality_gate - company_intel - tailor_resume - translate - cover_letter description: A single preparation step within the application-preparer pipeline example: tailor_resume stepsSkipped: type: array items: type: object properties: reason: type: string step: type: string enum: - quality_gate - company_intel - tailor_resume - translate - cover_letter description: A single preparation step within the application-preparer pipeline example: tailor_resume required: - reason - step additionalProperties: false description: A step the server will skip on the next re-prepare run, with a human-readable reason. tokensUsed: type: integer minimum: 0 required: - id - stepsRun - stepsSkipped - tokensUsed additionalProperties: false ApiErrorResponse: type: object properties: error: type: object properties: code: type: string context: oneOf: - type: object properties: errorType: type: string enum: - validation field: type: string fieldErrors: type: array items: type: object properties: code: type: string expected: type: string field: type: string message: type: string received: type: string required: - field - message schemaName: type: string required: - errorType - type: object properties: attemptedEmail: type: string format: email errorType: type: string enum: - authentication failureReason: type: string enum: - invalid_credentials - account_locked - expired_token - token_expired - missing_token - invalid_token - session_expired description: Reason for authentication failure example: token_expired ipAddress: type: string operation: type: string service: type: string userAgent: type: string required: - errorType - type: object properties: actualPermission: type: string errorType: type: string enum: - authorization requiredPermission: type: string resource: type: string resourceId: type: string userId: type: string required: - errorType - type: object properties: constraint: type: string errorType: type: string enum: - database operation: type: string enum: - insert - update - delete - select - batch - transaction - migration description: Type of database operation example: select resourceId: type: string sqlState: type: string table: type: string userId: type: string required: - errorType - type: object properties: endpoint: type: string errorType: type: string enum: - external_service httpStatus: type: number operation: type: string resourceId: type: string responseTime: type: number retryAttempt: type: integer service: type: string serviceName: type: string userId: type: string required: - errorType - type: object properties: errorType: type: string enum: - resource resource: type: string resourceId: type: string service: type: string userId: type: string required: - errorType - type: object properties: errorType: type: string enum: - rate_limit limit: type: number resetTime: type: string windowMs: type: number required: - errorType - type: object properties: configKey: type: string errorType: type: string enum: - configuration operation: type: string service: type: string required: - errorType description: Type-safe error context information example: errorType: validation fieldErrors: - field: email message: Invalid email format details: oneOf: - type: object properties: detailType: type: string enum: - validation validationErrors: type: array items: type: object properties: code: type: string field: type: string message: type: string required: - field - message required: - detailType - validationErrors additionalProperties: false - type: object properties: detailType: type: string enum: - service_error originalError: type: string serviceName: type: string required: - detailType - serviceName additionalProperties: false - type: object properties: currentSize: type: number detailType: type: string enum: - batch originalError: type: string statementCount: type: number required: - detailType additionalProperties: false - type: object properties: detailType: type: string enum: - rate_limit limit: type: number resetTime: type: string windowMs: type: number required: - detailType - limit - resetTime - windowMs additionalProperties: false - type: object properties: conflictingField: type: string detailType: type: string enum: - resource resourceId: anyOf: - type: string - type: number resourceType: type: string required: - detailType additionalProperties: false - type: object properties: detailType: type: string enum: - generic info: type: string required: - detailType additionalProperties: false - type: object properties: currentTokens: type: integer minimum: 0 detailType: type: string enum: - insufficient_tokens requiredTokens: type: integer minimum: 0 required: - currentTokens - detailType - requiredTokens additionalProperties: false message: type: string validation: type: array items: type: object properties: code: type: string field: type: string message: type: string required: - field - message additionalProperties: false required: - code - message additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - false required: - error - success additionalProperties: false securitySchemes: BearerAuth: description: 'Session token from signing in to AI Applyd, sent as `Authorization: Bearer `.' scheme: bearer type: http