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: Applyd AI API version: 115c47ce servers: - description: Current environment url: https://api.aiapplyd.com/api/v1 security: - BearerAuth: [] tags: - name: AI paths: /ai/status: get: tags: - AI summary: Get AI Status description: Get the AI status and stats for the authenticated user. parameters: - schema: type: integer minimum: 1 maximum: 100 default: 20 description: Results per page (max 100) example: 20 required: false description: Results per page (max 100) name: limit in: query - schema: type: integer minimum: 1 default: 1 description: Page number (1-based) example: 1 required: false description: Page number (1-based) name: page in: query - schema: type: string enum: - active - paused - completed description: Filter by application status example: active required: false description: Filter by application status name: status in: query responses: '200': description: AI status and stats content: application/json: schema: $ref: '#/components/schemas/ConfigListResponse' '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: getAiStatus /ai/activate: post: tags: - AI summary: Activate AI description: Activate AI for the user or return existing status. Creates AI persona entry if needed. requestBody: content: application/json: schema: $ref: '#/components/schemas/EnsureConfigRequest' responses: '200': description: Existing or newly created AI configuration content: application/json: schema: $ref: '#/components/schemas/EnsureConfigResponse' '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: postAiActivate /ai/quality-check: post: tags: - AI summary: Quality Gate Check description: Pre-apply quality assessment for a job against AI criteria. requestBody: content: application/json: schema: $ref: '#/components/schemas/QualityCheckRequest' responses: '200': description: Quality check result content: application/json: schema: $ref: '#/components/schemas/QualityCheckResponse' '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: postAiQualityCheck /ai/quality-stats: get: tags: - AI summary: Quality Gate Statistics description: Aggregated quality gate statistics for AI applications. responses: '200': description: Quality gate statistics content: application/json: schema: $ref: '#/components/schemas/QualityStatsResponse' '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: getAiQualityStats /ai/run: post: tags: - AI summary: Run AI Processing description: Process eligible job matches for active AI. Prepares application materials and creates results. responses: '200': description: AI run results content: application/json: schema: $ref: '#/components/schemas/RunApplicationsResponse' '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: postAiRun /ai/quota: get: tags: - AI summary: Get AI Quota Status description: Returns daily, weekly, and monthly quota usage and limits for AI applications. responses: '200': description: Quota status for AI applications content: application/json: schema: $ref: '#/components/schemas/ApplicationQuotaResponse' '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: getAiQuota components: schemas: QualityCheckData: type: object properties: matchConfidence: type: integer minimum: 0 maximum: 100 matchingSkills: type: array items: type: string missingSkills: type: array items: type: string recommendation: type: string enum: - apply - review - skip description: AI recommendation for whether to apply to a job example: apply suggestions: type: array items: type: string required: - matchConfidence - matchingSkills - missingSkills - recommendation - suggestions additionalProperties: false ConfigListResponse: type: object properties: data: type: object properties: items: type: array items: $ref: '#/components/schemas/ApplicationConfigData' pagination: type: object properties: hasNext: type: boolean hasPrev: type: boolean limit: type: integer description: Positive integer example: 1 exclusiveMinimum: 0 page: type: integer description: Positive integer example: 1 exclusiveMinimum: 0 pages: type: integer description: Positive integer example: 1 exclusiveMinimum: 0 total: type: integer minimum: 0 description: Non-negative integer example: 0 required: - hasNext - hasPrev - limit - page - pages - total additionalProperties: false required: - items - pagination additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Paginated response with items and pagination metadata QuotaPeriodInfo: type: object properties: limit: type: number description: Max allowed per period example: 5 remaining: type: number description: Remaining in current period example: 3 resetAt: type: - string - 'null' format: date-time description: When the period resets (null if not exhausted) example: '2026-04-01T00:00:00.000Z' used: type: number description: Used in current period example: 2 required: - limit - remaining - resetAt - used additionalProperties: false RunApplicationsResponse: type: object properties: data: $ref: '#/components/schemas/RunApplicationsData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response QualityStatsData: type: object properties: approved: type: integer averageConfidence: type: - number - 'null' blocked: type: integer flagged: type: integer totalChecked: type: integer required: - approved - averageConfidence - blocked - flagged - totalChecked additionalProperties: false QualityStatsResponse: type: object properties: data: $ref: '#/components/schemas/QualityStatsData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response 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 FreeApplicationsAllowance: type: object properties: limit: type: integer minimum: 0 description: Preparations a free account may run inside the rolling window. example: 3 remaining: type: integer minimum: 0 description: Preparations left. Zero means the swipe must be refused before it fires. example: 0 resetAt: type: string description: ISO timestamp the oldest consumed attempt ages out. example: '2026-10-01T00:00:00.000Z' used: type: integer minimum: 0 description: Preparations already consumed. Failed preparations are NOT counted. example: 3 required: - limit - remaining - resetAt - used additionalProperties: false ApplicationConfigData: type: object properties: status: type: string enum: - active - paused - completed description: Status of an AI agent config example: paused totalApplications: type: integer description: Postings the user has applications against, one unit each. Every other counter except totalEmployerReceipts is a slice of it and they sum to it exactly. Absent means not computed, which is NOT the same as zero. example: 49 totalApplied: type: integer description: 'Applications with retained employer proof: a linked employer receipt or a retained post-submit screenshot audited as employer confirmation. A legacy applied status or landing confidence grade alone does not count.' example: 3 totalErrors: type: integer totalSkipped: type: integer totalSubmitConfirmed: type: integer totalSubmitClicked: type: integer totalDeadPostings: type: integer description: Applications whose posting no longer exists (job_closed / job_removed). Excluded from every other counter and from every rate, in both numerator and denominator. Absent means not computed, which is NOT the same as zero. example: 2 totalEmployerReceipts: type: integer description: Distinct linked employer or ATS confirmation emails. OVERLAPS totalApplied and must not be summed with the partitioning counters. Absent means not computed, which is NOT the same as zero. example: 0 totalPendingReview: type: integer description: Postings whose newest row the USER parked for review (pending_review with a copilot apply mode). Never a row our own worker parked. Absent means not computed, which is NOT the same as zero. example: 1 totalQueuedToApply: type: integer description: 'Postings we will submit or retry without the user: newest row pending / ready_to_submit, or a pending_review row our worker parked and the backstop retries. Absent means not computed, which is NOT the same as zero.' example: 2 required: - status - totalApplied - totalErrors - totalSkipped - totalSubmitConfirmed - totalSubmitClicked additionalProperties: false ApplicationQuotaResponse: type: object properties: data: type: object properties: allowed: type: boolean description: Whether user can submit applications right now blockingPeriod: type: - string - 'null' enum: - monthly - daily - weekly - lifetime - none - null description: Which period is blocking, if any example: monthly daily: $ref: '#/components/schemas/QuotaPeriodInfo' earnedAppliesRemaining: type: integer minimum: 0 description: Earned applications available to an unpaid user after a converting referral signup freeApplications: $ref: '#/components/schemas/FreeApplicationsAllowance' hasAppliedBefore: type: boolean description: Whether this account already has at least one application result. False means the next apply is their first ever. example: true monthly: $ref: '#/components/schemas/QuotaPeriodInfo' planDailyMax: type: number description: Plan daily limit for capping persona dailyLimit example: 10 weekly: $ref: '#/components/schemas/QuotaPeriodInfo' required: - allowed - blockingPeriod - daily - earnedAppliesRemaining - freeApplications - hasAppliedBefore - monthly - planDailyMax - weekly additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response EnsureConfigRequest: type: object properties: {} additionalProperties: false QualityCheckResponse: type: object properties: data: $ref: '#/components/schemas/QualityCheckData' meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response EnsureConfigResponse: type: object properties: data: type: object properties: status: type: string enum: - active - paused - completed description: Status of an AI agent config example: paused totalApplications: type: integer description: Postings the user has applications against, one unit each. Every other counter except totalEmployerReceipts is a slice of it and they sum to it exactly. Absent means not computed, which is NOT the same as zero. example: 49 totalApplied: type: integer description: 'Applications with retained employer proof: a linked employer receipt or a retained post-submit screenshot audited as employer confirmation. A legacy applied status or landing confidence grade alone does not count.' example: 3 totalErrors: type: integer totalSkipped: type: integer totalSubmitConfirmed: type: integer totalSubmitClicked: type: integer totalDeadPostings: type: integer description: Applications whose posting no longer exists (job_closed / job_removed). Excluded from every other counter and from every rate, in both numerator and denominator. Absent means not computed, which is NOT the same as zero. example: 2 totalEmployerReceipts: type: integer description: Distinct linked employer or ATS confirmation emails. OVERLAPS totalApplied and must not be summed with the partitioning counters. Absent means not computed, which is NOT the same as zero. example: 0 totalPendingReview: type: integer description: Postings whose newest row the USER parked for review (pending_review with a copilot apply mode). Never a row our own worker parked. Absent means not computed, which is NOT the same as zero. example: 1 totalQueuedToApply: type: integer description: 'Postings we will submit or retry without the user: newest row pending / ready_to_submit, or a pending_review row our worker parked and the backstop retries. Absent means not computed, which is NOT the same as zero.' example: 2 created: type: boolean description: Whether the application configuration was newly created (true) or already existed (false) example: false required: - status - totalApplied - totalErrors - totalSkipped - totalSubmitConfirmed - totalSubmitClicked - created additionalProperties: false meta: $ref: '#/components/schemas/ResponseMetadata' success: type: boolean enum: - true required: - data - success additionalProperties: false description: Successful API response RunApplicationsData: type: object properties: processed: type: integer applied: type: integer skipped: type: integer errors: type: integer pendingReview: type: integer status: type: string enum: - processing - completed - no_matches description: Processing status. "processing" means heavy work was offloaded to background. example: processing required: - processed - applied - skipped - errors - pendingReview 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 QualityCheckRequest: type: object properties: jobDescription: type: string minLength: 1 maxLength: 5000 description: Job description text to evaluate example: We are looking for a Senior Software Engineer with 5+ years of experience... resumeContent: type: string maxLength: 10000 description: Resume content to match against the job description required: - jobDescription additionalProperties: false securitySchemes: BearerAuth: description: 'Session token from signing in to AI Applyd, sent as `Authorization: Bearer `.' scheme: bearer type: http