Skip to main content
API Reference

AILAT API v1.0.1

An adaptive testing API that measures AI literacy across four dimensions. Create assessments, submit answers, and retrieve personalized results from your LMS, HR tool, or custom application.

Base URL

https://ailat.io/api/v1

Auth

Bearer token

Rate limit

100 req / min

Getting started

Overview

The AILAT API powers the AI Literacy Assessment Test — an IRT-informed adaptive assessment. A single integration exposes 20-question sessions, adaptive item selection, evaluated open-ended responses, and a full results profile with a personalized learning path.

base URL
https://ailat.io/api/v1

Authentication

Every request requires a bearer token. Use the API inquiry form to request one.

header
Authorization: Bearer YOUR_API_TOKEN

Auth errors return a unified Authentication failed. response for all failure modes to prevent token enumeration.

Quick start

A typical integration follows five steps.

  1. 1
    Create. POST /assessments — returns the first question.
  2. 2
    Present. Render the returned question to the user.
  3. 3
    Submit. POST /assessments/{id}/answers — the response includes the next question.
  4. 4
    Repeat. Continue steps 2 – 3 until assessment_complete: true.
  5. 5
    Fetch. GET /assessments/{id}/results — full literacy profile.

Phases

PhaseQuestionsDescription
Calibration5Mixed-difficulty baseline across all dimensions.
Adaptive102PL item-information selection targeting the weakest area. Includes 2 open-ended.
Scenario5Industry-specific context with 1 open-ended capstone.

Core concepts

Assessment lifecycle

Sessions move through a small state machine. Pausing is client-initiated (there is no automatic idle pause); resume with a status update before submitting more answers. Retention is governed by the privacy notice: 7 days idle for in-progress or paused sessions, 90 days after completion.

state transitions
created  ──▶  in_progress  ──▶  pending_results  ──▶  completed
                 │                ▲                                   (on retry)
                 ▼                │
              paused  ────────────┘
                 │
                 ▼  (closed bank exhausted)
      incomplete_inventory   — answers kept, no literacy level awarded
StatusMeaning
in_progressAssessment is active and accepting answers.
pausedPaused by the client via PUT /status.
completedAll questions answered and results are available.
pending_resultsAll questions answered; results are still being generated.
incomplete_inventoryThe approved question bank ran out of eligible items (closed generated-item policy). Answers are kept; GET /results returns incomplete: true with no literacy level.

Pending results: if results generation is still in progress, GET /results returns HTTP 202 with a Retry-After: 30 header.

Replay and conflicts: re-sending an identical answer for an already-recorded question replays the stored outcome in every state, including completed, with replayed: true. A different answer for the same question, or a write that lost a concurrent-modification race, returns 409. A dependency outage returns 503 with Retry-After; bodies over 64 KB return 413.

Open-ended evaluation: if no scoring provider answers, the response carries evaluation.status: "failed" and no score. The answer is retried by a durable job; a later success republishes the result as a new result_version. Unscored answers never count as partial credit. While a corrected score is still unpublished, GET /results returns 202 with Cache-Control: no-store and the stale and current scoring revisions, never the outdated result as a cacheable 200.

Completion reasons: completion_reason on a result is one of complete, inventory_exhausted (closed bank ran out of eligible items), evaluation_unavailable (open-ended evaluations failed and the evidence floor was not met) or insufficient_evidence (all items administered but a dimension is below its scored-item floor). A result is incomplete: true whenever the reason is not complete, and no literacy level is awarded.

HTTP status codes

Errors share a consistent shape. Check recovery_action for user-facing guidance.

CodeMeaning
200Success.
202Accepted — results are still being generated; retry after delay.
400Bad request — invalid parameters, idle session, or completed assessment.
401Unauthorized — invalid or missing token.
403Forbidden — token lacks access to the requested resource.
404Not found — assessment or resource does not exist.
429Rate limited — check Retry-After header.
500Server error.
501Not implemented — feature planned for v1.1.
503Service unavailable — retry in 30s.
error shape
{
  "success": false,
  "error": "ValidationError",
  "message": "Human-readable description",
  "details": { },
  "recovery_action": "What to do next"
}

Rate limits

100 requests per minute per API token. Exceeding the limit returns 429 with a Retry-After header. Use exponential backoff with jitter when retrying.

HeaderValue
X-RateLimit-Limit100
X-RateLimit-RemainingApproximate remaining requests.

Endpoints

Endpoints

Each endpoint speaks JSON and returns the shape shown. {id} is the assessment identifier returned from the create call.

POST/assessments

Create assessment

Creates a new assessment and returns the first question.

Request

FieldTypeRequiredDescription
industryenumYesOne of the industry values listed below.
rolestringYesUser's professional role.
motivationenumNoOne of the motivation values listed below.
organization_idstringNoOrganization identifier; org-tagged assessments are access-controlled and require a matching org-scoped API token.
user_idstringNoUser identifier for tracking.

Response

json
{
  "success": true,
  "assessment_id": "asmt_abcdef123456",
  "status": "in_progress",
  "current_question": {
    "question_id": "Q1",
    "question_text": "...",
    "question_type": "multiple_choice",
    "options": {
      "A": "...",
      "B": "...",
      "C": "...",
      "D": "..."
    },
    "dimension": "CONCEPTUAL_KNOWLEDGE"
  },
  "progress": {
    "questions_completed": 0,
    "total_questions": 20,
    "percent_complete": 0
  }
}

Valid industry values

Value
Academia & Education
Agriculture, Forestry & Fishing
Arts, Entertainment & Media
Construction & Real Estate
Energy & Utilities
Financial Services
Government & Public Sector
Healthcare & Social Services
Hospitality & Tourism
Information Technology
Legal Services
Manufacturing
Professional Services
Retail & Consumer Goods
Science & Research
Telecommunications
Transportation & Logistics
Wholesale & Distribution
General

Valid motivation values

ValueMeaning
Professional DevelopmentFor current job role improvement
Career TransitionMoving to a new AI-related role
Academic LearningFor educational purposes
LeadershipFor managing teams using AI
Personal InterestGeneral curiosity about AI
Organizational AssessmentUnderstanding team capabilities
CertificationPreparing for formal certification
Required TrainingMandated by organization
GET/assessments/{id}

Get assessment state

Returns the current question and progress. Use this to resume after a page reload.

Response headers: Cache-Control: no-store. Response shape matches the create call for assessments that are still in progress.

Status-specific behavior

Assessment statusBehavior
in_progress / pausedReturns the current question and progress.
completedReturns 400 with results_url in the body. Follow the URL to fetch results.
pending_resultsReturns 400 with results_url. Retry GET /results until ready.
Session cleaned up but result existsReturns 400 with results_url. Bookmarked assessment URLs remain resolvable after the session retention window.
POST/assessments/{id}/answers

Submit answer

Submits an answer and returns the next question, or completion status.

Request

FieldTypeRequiredDescription
question_idstringYesID of the question being answered.
answerstringYesA/B/C/D for multiple-choice, or free text for open-ended.
response_time_msnumberNoMilliseconds spent answering (capped at 600,000).

Response

multiple-choice, in progress
{
  "success": true,
  "is_correct": false,
  "correct_answer": "C",
  "explanation": "...",
  "next_question": { ... },
  "progress": { "questions_completed": 1, "total_questions": 20, "percent_complete": 5 },
  "assessment_complete": false
}

Idempotency

Re-submitting the same question_id with the same answer returns the cached result instead of an error. This makes network-timeout retries safe. Re-submissions with a different answer for the same question are rejected with a 400.

Replays deliberately omit correct_answer and explanation so the answer key isn't re-exposed on every retry — read those fields from the original response.

Open-ended response shape

json
{
  "success": true,
  "evaluation": {
    "overall_score": 0.85,
    "feedback": "Your explanation demonstrates excellent understanding..."
  },
  "next_question": { ... },
  "progress": { ... },
  "assessment_complete": false
}

Complete response

json
{
  "success": true,
  "is_correct": true,
  "correct_answer": "C",
  "explanation": "...",
  "assessment_complete": true,
  "results_url": "/api/v1/assessments/asmt_abcdef123456/results",
  "progress": { "questions_completed": 20, "total_questions": 20, "percent_complete": 100 }
}
PUT/assessments/{id}/status

Update assessment status

Pause or resume an assessment.

Request

FieldTypeRequiredDescription
statusstringYes"paused" or "in_progress".

Response

json
{
  "success": true,
  "assessment_id": "asmt_abcdef123456",
  "status": "paused",
  "resume_url": "/api/v1/assessments/asmt_abcdef123456",
  "expires_at": "2025-04-07T14:30:45Z"
}

completed and pending_results are system-managed and cannot be set manually.

GET/assessments/{id}/results

Get assessment results

Returns the full results of a completed assessment.

Response headers: Cache-Control: private, max-age=3600

Status-specific behavior

Assessment statusBehavior
completedReturns results immediately.
pending_resultsAttempts to generate results; returns 202 with Retry-After: 30 if still pending.
Other statusesReturns 400.

Response

json
{
  "success": true,
  "assessment_id": "asmt_abcdef123456",
  "user_id": "user_xyz789",
  "organization_id": "org_abc123",
  "completed_at": "2025-04-05T15:15:12Z",
  "duration_minutes": 45,
  "overall_score": 75.3,
  "ai_literacy_level": 4,
  "level_details": {
    "title": "Critical Evaluator",
    "description": "Proficient understanding and skilled application of AI.",
    "indicators": [
      "Regularly applies AI tools to solve complex problems",
      "Can critically evaluate AI outputs",
      "Understands technical limitations of AI systems",
      "Considers ethical implications of AI use"
    ]
  },
  "dimension_scores": {
    "CONCEPTUAL_KNOWLEDGE": 85.0,
    "USE_APPLY_KNOWLEDGE": 75.0,
    "EVALUATE_CREATE_KNOWLEDGE": 70.0,
    "ETHICS_KNOWLEDGE": 65.0
  },
  "strengths": [ "Strong understanding of AI concepts and terminology" ],
  "growth_areas": [ "Enhance awareness of AI ethics and responsible use" ],
  "learning_path": {
    "focus_areas": [
      { "title": "Responsible AI use", "explanation": "Learn the bias, privacy and accountability questions that matter for your work." },
      { "title": "Judging AI outputs", "explanation": "Practise checking AI-generated work for errors before you act on it." }
    ],
    "resources": [
      {
        "title": "AI Ethics: Principles for Professionals",
        "type": "course",
        "url": "https://example.com/ai-ethics",
        "relevance": "Tailored to Healthcare & Social Services. Builds ethics, bias and privacy in AI."
      }
    ],
    "next_steps": [
      "Pick one AI tool you used this week and write a short note on what it got wrong.",
      "Map two ethical risks from your last project and the safeguard you would add next time."
    ]
  },
  "answer_insights": {
    "average_response_time_ms": 45000,
    "fastest_dimension": "CONCEPTUAL_KNOWLEDGE",
    "slowest_dimension": "ETHICS_KNOWLEDGE",
    "consistent_errors": []
  }
}
GET/assessments/{id}/status

Get assessment status

Lightweight status check without the current question.

json
{
  "success": true,
  "assessment_id": "asmt_abcdef123456",
  "status": "in_progress",
  "user_id": "user_xyz789",
  "organization_id": "org_abc123",
  "created_at": "2025-04-05T13:15:12Z",
  "last_activity": "2025-04-05T13:25:42Z",
  "progress": { "questions_completed": 8, "total_questions": 20, "percent_complete": 40 },
  "expires_at": "2025-04-06T13:25:42Z"
}
GET/organizations/{organizationId}/results

Organization results

Aggregated analytics for an organization.

Response headers: Cache-Control: private, max-age=600

Query parameters

FieldTypeRequiredDescription
time_periodstringNoall_time (default), last_7_days, last_30_days, last_90_days, current_year.

Aggregates only. The response never contains individual participant rows, time buckets, or pagination. Fewer than 5 completed assessments in the window returns the insufficient-sample shape below (coverage counts only, no scores); role and department breakdowns are additionally suppressed for any group under 5 completions.

Cohort semantics: a cohort is the set of assessments whose start time falls in the requested window. total_assessments is the cohort size. completed_assessments is the number of cohort members that reached completed at any time up to the observation cutoff (observed_at, the request time). completion_rate is completed divided by started and cannot exceed 100. Completions in the window by assessments started before it are reported separately as completed_in_window and are not part of the rate. Incomplete (no-grade) results are counted in incomplete_assessments and excluded from every average. Start events are recorded from a published ledger watermark (2026-09-05); for a window that begins earlier, completion_rate is null with a completion_rate_note — it is never estimated. Rolling windows compare exact start timestamps against the cutoff.

Response (abbreviated)

json
{
  "success": true,
  "organization_id": "org_abc123",
  "insufficient_sample": false,
  "min_group_size": 5,
  "total_assessments": 25,
  "completed_assessments": 23,
  "incomplete_assessments": 0,
  "observed_at": "2025-04-05T15:20:00Z",
  "average_score": 72.5,
  "average_level": 3.6,
  "completion_rate": 92.0,
  "dimension_averages": {
    "CONCEPTUAL_KNOWLEDGE": 78.2,
    "USE_APPLY_KNOWLEDGE": 75.7,
    "EVALUATE_CREATE_KNOWLEDGE": 70.1,
    "ETHICS_KNOWLEDGE": 65.4
  },
  "strongest_dimension": "CONCEPTUAL_KNOWLEDGE",
  "weakest_dimension": "ETHICS_KNOWLEDGE",
  "time_period": { "filter": "all_time" },
  "level_distribution": { "1": 0, "2": 3, "3": 8, "4": 10, "5": 2 },
  "role_analytics": { "min_group_size": 5, "suppressed": true, "groups": {} }
}

Response · insufficient sample (fewer than 5 completions)

json
{
  "success": true,
  "organization_id": "org_abc123",
  "insufficient_sample": true,
  "min_group_size": 5,
  "total_assessments": 4,
  "completed_assessments": 3,
  "incomplete_assessments": 0,
  "completion_rate": 75,
  "observed_at": "2025-04-05T15:20:00Z",
  "message": "Fewer than 5 completed assessments; aggregate scores are withheld."
}
Planned · v1.1

Planned endpoints

Three endpoints return 501 today and are scheduled for v1.1.

MethodPathPurpose
POST/organizations/{id}/invitesBatch invite users.
GET/organizations/{id}/exportExport results.
POST/webhooksRegister a webhook for assessment events.

Reference

Dimensions & weights

Four dimensions contribute to the overall score with the weights below.

DimensionWeightWhat it measures
CONCEPTUAL_KNOWLEDGE30%AI fundamentals, terminology, capabilities, limitations.
USE_APPLY_KNOWLEDGE30%Practical application, prompt engineering, workflow integration.
EVALUATE_CREATE_KNOWLEDGE25%Critical assessment of AI outputs, quality evaluation.
ETHICS_KNOWLEDGE15%Bias, privacy, transparency, accountability.

Literacy levels

The overall score maps to one of five levels, each with its own learning-path profile.

LevelTitleRangeDescription
1Baseline Awareness0 ≤ score < 20Basic awareness, limited practical knowledge.
2Informed User20 ≤ score < 40Familiar with concepts, occasional tool use.
3Capable Practitioner40 ≤ score < 60Competent understanding, regular tool use.
4Critical Evaluator60 ≤ score < 80Proficient, can critically evaluate AI outputs.
5AI Champion80 ≤ score ≤ 100Advanced understanding, sophisticated application.

Adaptive testing

AILAT uses a 2-Parameter Logistic (2PL) Item Response Theory model. After each answer, the system updates the proficiency estimate and selects the next question to maximize Fisher information at that level.

Adaptive tracks

TrackProficiencyDifficulty mix
Foundational≤ −1.0Prioritizes EASY (70%) with some MEDIUM.
Standard−1.0 … 1.0Balanced mix based on IRT.
Advanced≥ 1.0Prioritizes DIFFICULT (70%) with some MEDIUM.

Error recovery

The API prioritizes assessment continuity. Most failure modes have an automatic fallback that keeps the session usable.

ScenarioWhat happens
Question bank exhaustedDepends on the active instrument's generated-item policy. legacy: an LLM fallback item is generated and scored. pretest: a generated item is served unscored. closed (audited banks): the answer is kept, the session enters incomplete_inventory with blocked: true, and no literacy level is awarded.
LLM evaluation unavailableThe answer is recorded with evaluation.status: "failed" and contributes nothing to any score; a durable job re-evaluates it and republishes the result as a new version. A result is written as incomplete when its instrument version's scored-evidence requirements are not met.
Results generation failsStatus set to pending_results; retry /results later.
Dependency unavailable (bank metadata, storage)Returns 503 with Retry-After; retry the same request.
Rate limiter unavailableReturns 503 with Retry-After: 30.
Network timeout on answerRe-submit the same answer (idempotent).

Best practices

Session management

  • Store assessment_id securely between requests.
  • Retention is 7 days idle for in-progress or paused sessions and 90 days after completion; there is no automatic idle pause.
  • Check expires_at to anticipate expiration.

Answer submission

  • Include response_time_ms when possible for response-time analytics.
  • Acceptable range: 5 – 60s for MC, 60 – 300s for open-ended.
  • The same answer can be safely re-submitted (idempotent, even after completion); a different answer for the same question returns 409.

Error handling

  • Retry with exponential backoff for 429 and 503.
  • Use recovery_action for user-facing guidance.
  • Poll on 202 for pending results.

Result visualization

  • Use radar charts for dimension scores.
  • Color-code literacy levels 1 – 5.
  • Highlight strengths (≥ 70%) and growth areas (< 60%).

Code examples

Drop-in patterns for the two most common integration headaches.

Retry with exponential backoff

retry.js
async function apiRequest(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);
    if (response.status === 429 || response.status === 503) {
      const retryAfter = response.headers.get('Retry-After') || 5;
      await new Promise((r) =>
        setTimeout(r, retryAfter * 1000 * Math.pow(2, i))
      );
      continue;
    }
    return response;
  }
  throw new Error('Max retries exceeded');
}

Poll for pending results

poll-results.js
async function getResults(assessmentId, token) {
  while (true) {
    const res = await fetch(
      `https://ailat.io/api/v1/assessments/${assessmentId}/results`,
      { headers: { Authorization: `Bearer ${token}` } }
    );
    if (res.status === 200) return res.json();
    if (res.status === 202) {
      const delay = res.headers.get('Retry-After') || 30;
      await new Promise((r) => setTimeout(r, delay * 1000));
      continue;
    }
    throw new Error(`Unexpected status: ${res.status}`);
  }
}

Support

Support

Changelog

v1.1.0

  • Industry identifiers unified: the API, the question bank, the importer and the picker share one 19-value list (Academia & Education, Legal Services, Science & Research, Retail & Consumer Goods, General, …). The old labels Education, Retail & E-commerce and General (Cross-industry) are still accepted and normalized.
  • Session writes are conflict-safe: creation is create-if-absent, activity and status changes are atomic, versions come only from stored state. A stale write can no longer erase an accepted answer or reopen a finished assessment (409 on conflict).
  • Answer replay works in every state, including completed, and returns the bound next question; a different answer for an already-answered question returns 409.
  • Served content is authoritative for scoring: retiring, editing or retyping a live bank row after it was served does not change what the participant can answer or how it is scored.
  • Failed open-ended evaluations are recorded as unscored evidence (evaluation.status: failed) instead of a silent 0.5, retried durably, and republished as a new result_version.
  • New terminal state incomplete_inventory for closed banks that run out of eligible items: answers are kept, GET /results returns incomplete: true and no literacy level; incomplete results are excluded from organization averages.
  • Results carry provenance: instrument version, bank digest(s) served, selection and generated-item policy, scoring route, per-dimension scored and unscored counts, pretest count, evaluator availability, completion_reason and result_version.
  • Organization results use cohort semantics with an observation cutoff (observed_at, completed_in_window, incomplete_assessments); windowed completion_rate is null with a note when start events do not cover the window instead of a manufactured 100%.
  • Request schemas are bounded (400 with field errors for wrong types; 100-character role/department; 413 for bodies over 64 KB) and analytics grouping is safe for any label.
  • Authorization is checked immediately after lookup on every participant route, so a foreign organization receives an identical 403 regardless of session state.
  • The documented 30-minute automatic pause was never enforced and has been removed from the contract; pausing is client-initiated. Retention: 7 days idle, 90 days after completion.
  • Post-review fixes: adaptive selection keeps the v2 evidence floor feasible for every participant; a bank outage is a 503, never inventory exhaustion; failed evaluations retry durably outside the object lock and republish automatically; GET /results returns 202 while a corrected score is unpublished; privacy erasure removes retained cohort start keys and the admin export returns every result version; completion_reason distinguishes insufficient_evidence.

v1.0.3

  • Completed assessments remain viewable indefinitely — GET /assessments/{id}/results now serves directly from the immutable result record without requiring the underlying session to still exist.
  • GET /assessments/{id} now redirects (400 + results_url) when the session has been cleaned up but a result still exists, so bookmarked assessment URLs continue to resolve after the retention window.
  • Session retention switched from a flat 24h KV TTL to a Durable Object alarm: 7 days idle for in-progress / paused, 90 days after completion. The expires_at field on /status responses now reflects the real retention deadline.
  • PUT /assessments/{id}/status now rejects pending_results in addition to completed.
  • Errors now always return JSON. Previously some thrown errors fell through to a plain-text 500; clients no longer have to parse non-JSON responses.
  • Internal 5xx error messages are no longer disclosed to clients — server-side detail stays in worker logs while clients receive a generic message.
  • Authorization is now checked before any session-mutating helper runs on GET /assessments/{id} and POST /assessments/{id}/answers.
  • Organization analytics index switched from a mutable JSON array to per-result marker keys, eliminating lost-update races on concurrent completions.

v1.0.1

  • Adaptive track thresholds adjusted from ±1.5 to ±1.0 for better responsiveness.
  • Adaptive track re-evaluation was announced here but shipped only as assignment on entering the adaptive phase (selection policy v1); per-answer reassignment ships as selection policy v2 with instrument v2.
  • A 30-minute automatic pause was announced here but never enforced; removed from the contract in v1.1.0.
  • Answer submission is idempotent (safe to retry on network timeout).
  • Pending results return 202 instead of 500.
  • Unimplemented endpoints return 501 with clear messaging.
  • Added strongest_dimension, weakest_dimension, time_period to organization results.
  • Added Cache-Control headers to results and analytics endpoints.
  • Rate limiter fails closed (503) instead of silently bypassing.
  • Authentication errors unified to prevent token enumeration.

v1.0.0

  • Initial API release.
  • Core assessment endpoints.
  • Organization analytics.
  • Adaptive item selection using a 2PL model.
  • Learning path recommendations.

Planned for v1.1

  • Batch invitations (POST /organizations/{id}/invites).
  • Data export (GET /organizations/{id}/export).
  • Webhook notifications (POST /webhooks).
  • Enhanced organization management.

All timestamps use ISO 8601 format. All IDs use the prefix pattern (asmt_, org_, user_).