Skip to main content

AI Service API

The AI Service GraphQL API powers all artificial intelligence and machine learning operations on the AIQLick platform. Built with FastAPI and Strawberry GraphQL, it specializes in real-time streaming of AI processing progress through GraphQL subscriptions.

Endpoint: https://ai.aiqlick.com/graphql (production) | https://ai-dev.aiqlick.com/graphql (development)

Authentication

The AI Service validates the same JWT tokens issued by the Backend. For HTTP requests, include the token in the Authorization header. For WebSocket subscriptions, pass the token in connectionParams:

{
"connectionParams": {
"token": "<jwt_token>"
}
}

Subscriptions

The AI Service provides 12 GraphQL subscriptions that stream real-time progress as AI operations execute. Each subscription emits typed events so the frontend can display live feedback to users.

CV Extraction

Parses uploaded CV documents into structured data fields (name, email, experience, education, skills, etc.). The union also includes a CVExtractionPartial variant that streams as each of the 5 parallel extraction schemas lands plus the pre-flight classifier verdict (step="classification"). See CV & Job Extraction for the architectural detail.

subscription {
extractCv(input: { file_url: "...", id: "...", sequential: true, company_id: "...", user_id: "..." }) {
... on CVExtractionProcessing {
percentage
message
}
... on CVExtractionPartial {
step # "contact" | "skills" | "education" | "experience" | "metadata" | "classification"
partialJson # JSON-encoded slice — frontend JSON.parse + merges into form state
}
... on CVExtractionSuccess {
parsedCv {
id
fields
}
}
... on CVExtractionFailure {
code
message
}
}
}

Job Parsing

Parses job descriptions into structured fields (title, requirements, responsibilities, qualifications). Mirrors the CV pattern: the union includes a JobParsingPartial variant that streams as each of the 4 converged extraction steps lands (core_info, requirements_qualifications, responsibilities_skills, compensation_benefits) plus the pre-flight classifier verdict (step="classification").

subscription {
parseJob(input: { jobId: "...", companyId: "..." }) {
... on JobParsingProcessing {
percentage
message
}
... on JobParsingPartial {
step # "core_info" | "requirements_qualifications" | "responsibilities_skills" | "compensation_benefits" | "classification"
partialJson
}
... on JobParsingSuccess {
parsedJob {
id
fields
}
}
... on JobParsingFailure {
code
message
}
}
}

Face Extraction

Detects and extracts face images from CV documents using AWS Rekognition.

subscription {
faceExtraction(input: { cvId: "...", userId: "..." }) {
... on FaceExtractionProcessing {
percentage
message
}
... on FaceExtractionSuccess {
faceUrl
}
... on FaceExtractionFailure {
code
message
}
}
}

Add Candidate

Executes the full candidate onboarding pipeline: CV extraction, face detection, data validation, and candidate record creation.

subscription {
addCandidate(input: { cvId: "...", jobId: "...", companyId: "..." }) {
... on AddCandidateProcessing {
percentage
stage
message
}
... on AddCandidateSuccess {
candidate {
id
status
}
}
... on AddCandidateFailure {
code
message
}
}
}

Job Matching

Two matching subscriptions calculate compatibility scores between profiles and jobs.

User-Job Matching scores a user profile against a job posting:

subscription {
userJobMatching(input: { userId: "...", jobId: "...", companyId: "..." }) {
... on UserJobMatchingProcessing {
percentage
message
}
... on UserJobMatchingSuccess {
score
breakdown
}
... on UserJobMatchingFailure {
code
message
}
}
}

Candidate-Job Matching scores an existing candidate against their assigned job:

subscription {
candidateJobMatching(input: { candidateId: "...", companyId: "..." }) {
... on CandidateJobMatchingProcessing {
percentage
message
}
... on CandidateJobMatchingSuccess {
score
breakdown
}
... on CandidateJobMatchingFailure {
code
message
}
}
}

Basic Matching

Performs simple skill-based matching without the full AI scoring pipeline.

subscription {
basicMatching(input: { talentId: "...", jobId: "..." }) {
... on BasicMatchingProcessing {
percentage
}
... on BasicMatchingSuccess {
score
matchedSkills
}
... on BasicMatchingFailure {
code
message
}
}
}

Text Rewrite

Rewrites text content using AI, useful for improving job descriptions, summaries, and profiles.

subscription {
textRewrite(input: { text: "...", style: "professional", companyId: "..." }) {
... on TextRewriteProcessing {
percentage
}
... on TextRewriteSuccess {
rewrittenText
}
... on TextRewriteFailure {
code
message
}
}
}

Meeting Insight

Generates AI-powered analysis of meeting transcripts, including summaries, action items, and participant assessments. Supports versioning for live updates during ongoing meetings.

subscription {
generateMeetingInsight(input: { meetingId: "...", companyId: "..." }) {
... on MeetingInsightProcessing {
percentage
message
}
... on MeetingInsightSuccess {
insight {
id
summary
actionItems
version
}
}
... on MeetingInsightFailure {
code
message
}
}
}

Agent Chat

Streams AI agent responses in real-time. This subscription emits a sequence of typed events as the agent processes the user's message, executes tools, and generates a response.

subscription {
agentChat(input: { agentId: "...", conversationId: "...", message: "..." }) {
... on ChatProcessing {
message
}
... on ChatContextLoaded {
documentCount
tokenCount
}
... on ChatChunk {
content
index
}
... on ChatReasoningChunk {
delta
chunkIndex
}
... on ChatToolCall {
toolName
arguments
}
... on ChatToolResult {
toolName
result
}
... on ChatComplete {
fullResponse
usage {
inputTokens
outputTokens
creditCost
}
}
... on ChatError {
code
message
}
}
}

Event sequence: ChatProcessing --> ChatContextLoaded --> ChatReasoningChunk (repeated, only when the agent's model supports extended thinking) --> ChatChunk (repeated) --> ChatToolCall / ChatToolResult (optional, repeated) --> ChatComplete or ChatError.

Event dedup (SUP-00077, 2026-04-21)

The subscription handler dedupes three event classes per turn so Bedrock's multi-hop tool loop cannot re-emit the same content:

  • ChatChunk — deduped by chunk_index
  • ChatToolCall — deduped by tool_call_id
  • ChatToolResult — deduped by tool_call_id

Clients can therefore treat each event as the definitive version without needing their own idempotency layer.

ChatReasoningChunk

ChatReasoningChunk carries the model's extended-thinking deltas (Claude Sonnet 4.x / Opus 4.x). Render in a separate "Reasoning" surface — never concatenate into the final response. Clients that omit the inline fragment will receive the events with all fields undefined and end up rendering empty/NaN blocks. See AI Agents → Reasoning Streaming.

ChatError codes

When ChatError is yielded, the code field is one of the values below — clients should special-case the billing/auth/attachment codes for targeted recovery hints, and fall through to a generic "try again" message for the rest.

CodeWhenWhat clients should do
CONVERSATION_NOT_FOUNDThe conversation id was deleted between subscribe and streamStart a new conversation
CONVERSATION_INACTIVEConversation is archivedReactivate or start a new one
UNAUTHORIZEDJWT missing/invalid OR conversation belongs to a different user/companyRe-auth, then retry
RATE_LIMITEDPer-agent maxMessagesPerMinute exceededWait and retry
TOKEN_LIMIT_EXCEEDEDPer-agent maxTokensPerDay exhaustedWait until reset or raise the limit
INSUFFICIENT_CREDITSPre-check failed at billingShow the credits-purchase flow
SUBSCRIPTION_INACTIVEPlan not ACTIVE/TRIALINGShow the activate-subscription flow
PLAN_LIMIT_EXCEEDEDOperation count exceeded plan capShow the upgrade-plan flow
ATTACHMENT_FAILEDA user-provided attachment couldn't be downloaded from S3 or its actual bytes exceed the size limit. Surfaced BEFORE the LLM call so no user/assistant rows are created.Restore pendingAttachments from a snapshot so the user can re-upload without losing their selections — see Attachment retry UX
CHAT_ERRORGeneric LLM/processing failureRetry the message
TOOL_ERRORTool execution failedCheck tool configuration

System Monitoring

Two subscriptions provide system-level observability.

Task Subscription streams task execution events:

subscription {
taskSubscription(taskId: "...") {
status
progress
result
error
}
}

Metrics Subscription streams periodic system metrics:

subscription {
metricsSubscription {
activeWorkers
queueDepth
processingRate
errorRate
}
}

Subscription Reference

SubscriptionPurposeProgress TypeBilling
extractCvCV parsing with structured data extractionPercentageCredits consumed
parseJobJob description parsingPercentageCredits consumed
faceExtractionFace detection from CV photosPercentageCredits consumed
addCandidateFull candidate onboarding pipelinePercentage + stageCredits consumed
userJobMatchingUser-job match scoringPercentageCredits consumed
candidateJobMatchingCandidate-job matchingPercentageCredits consumed
basicMatchingSimple skill matchingPercentageCredits consumed
textRewriteAI text rewritingPercentageCredits consumed
generateMeetingInsightMeeting analysis generationPercentageCredits consumed
agentChatStreaming AI agent chatChunked eventsCredits consumed
taskSubscriptionSystem task monitoringEvent-basedNone
metricsSubscriptionSystem metricsPeriodicNone

Error Types

All subscriptions can emit error events. The error types follow a consistent structure:

Error CodeDescription
VALIDATION_ERRORInvalid input parameters or missing required fields
PROCESSING_ERRORFailure during AI model invocation or data processing
TIMEOUT_ERROROperation exceeded the maximum allowed processing time
BILLING_ERRORInsufficient credits or inactive subscription

Error events include a code field and a human-readable message field:

{
"code": "BILLING_ERROR",
"message": "Insufficient credit balance. Required: 5 credits, available: 2 credits."
}

Billing Integration

All AI subscriptions (except system monitoring) consume credits. The AI Service uses a BillingGate that:

  1. Pre-checks the user's subscription status and credit balance before starting the operation.
  2. Executes the AI operation (LLM invocation, image processing, etc.).
  3. Consumes credits based on actual token usage after completion.

Credit routing depends on the user's view mode:

  • Employer mode (with selectedCompanyId): Credits are deducted from the company balance.
  • Job Seeker mode: Credits are deducted from the user's personal balance.

Each operation is logged in the AIOperationLog table with token counts and credit cost for audit purposes.