API v1

Material Review API

Submit a K–12 assessment or other learning material with questions or student tasks and receive Steletta's saved review: a verdict, Accuracy & Quality and Coverage scores, required fixes, suggested improvements and strengths.

Organization access

API keys are issued for approved organization integrations. Talk to us to discuss your catalog and workflow.

How a review works

  1. Submit one source.Send the original resource with its intended use, optional title or listing description, optional grade and a stable idempotency key.
  2. Review both levels.Individual tasks and document-wide relationships such as promises, section alignment, progression and scoring are checked independently, then combined in one saved review.
  3. Track the job.The API returns a review ID immediately. Poll its status as it moves from queued to processing and completed.
  4. Collect the saved result.The completed result contains the report produced by the Steletta review workflow. The API does not rewrite the report or manufacture fallback scores.

Review jobs use created, awaiting_upload, queued, processing, completed, failed or cancelled. While a job is non-terminal, follow the Retry-After header before polling again. Stop polling on any terminal status.

Access

The organization API, MCP integration and team access are included with Large Catalogs. Individual Creators and Steletta Pro use the Steletta dashboard. Webhook integration is available on request and quoted separately.

Monthly and annual billing within one tier have the same features. Organization API access requires a Large Catalogs agreement.

Use separate test and live keys so credentials can be rotated independently. A test key is not a free sandbox: its reviews still belong to the organization and consume the active agreement's allowance.

Quickstart

Use the approved HTTPS base URL ending in /api/v1. Keep API keys on your server and send them as bearer tokens.

curl https://www.steletta.com/api/v1/reviews \
  -H "Authorization: Bearer $STELETTA_API_KEY" \
  -H "Idempotency-Key: catalog-1042-v3" \
  -F "file=@assessment.pdf" \
  -F "purpose=prepublication_assessment" \
  -F "grade=6"

A new submission returns HTTP 202 and a job resource. A safe retry with the same idempotency key and identical inputs returns the existing job.

{
  "id": "rev_example",
  "status": "queued",
  "createdAt": "2026-09-08T12:00:00.000Z",
  "completedAt": null
}

Wait for completion

Poll GET /reviews/{reviewId} at a modest interval until the job completes, fails or is cancelled. The result endpoint returns HTTP 409 while the job is incomplete.

curl "$STELETTA_BASE_URL/reviews/rev_example/result" \
  -H "Authorization: Bearer $STELETTA_API_KEY"

Direct uploads

For server applications that should not proxy file bytes through their own request handler, use the three-step private upload flow:

  1. Prepare.Call POST /uploads with the filename, size, SHA-256 digest, purpose and an idempotency key. Steletta returns a short-lived private upload credential.
  2. Upload.Send the exact bytes to the returned private pathname. Do not log or store the upload credential.
  3. Complete.Call POST /uploads/{uploadId}/complete. Steletta verifies the size, checksum and document before creating one review.

If the upload response is lost, retry prepare with the original idempotency key and identical metadata. If completion returns a temporary error, retry the same upload ID after Retry-After. A completed replay returns the original review.

Sources and review limits

  • Send exactly one original PDF per review.
  • The current customer upload limit is 20 MiB.
  • ZIP archives and multiple-source submissions are rejected before model work begins.
  • Each source must be a K–12 assessment or other learning material with at least one question or student task. Sources without learner work end without a score or review card.
  • Resources with up to 250 learner tasks are reviewed asynchronously with the complete source kept together.
  • Resources above 250 learner tasks must be divided into independently reviewed sections of at most 250. Steletta does not automatically combine their scores.

Completed results

A completed result includes the decision, both scores and structured findings. Required fixes, improvements and strengths retain their evidence, location and recommended action when supplied by the saved review.

{
  "reviewId": "rev_example",
  "decision": "needs_fixes",
  "scores": {
    "accuracyQuality": 72,
    "coverage": 92
  },
  "findings": [
    {
      "id": "finding_01",
      "type": "required",
      "page": 2,
      "location": "Question 2",
      "title": "Two answer choices are correct",
      "evidence": "B (square) and D (rhombus) both have four equal sides. The key accepts only B",
      "suggestedAction": "Add \"and four right angles\" to make B the only correct answer"
    },
    {
      "id": "finding_02",
      "type": "required",
      "page": 4,
      "location": "Question 6 · Answer explanation",
      "title": "The explanation states a false rule",
      "evidence": "The explanation says absolute value is always positive, but the absolute value of zero is zero",
      "suggestedAction": "Explain absolute value as distance from zero, which is always nonnegative"
    },
    {
      "id": "finding_03",
      "type": "improvement",
      "page": 3,
      "location": "Question 4",
      "title": "Two equivalent choices can be ruled out",
      "evidence": "4/6 and 2/3 are equal. Because only one answer can be correct, learners can eliminate both without knowing the answer",
      "suggestedAction": "Replace one duplicate with a distinct wrong value, such as 3/8, so each choice tests a different misconception"
    },
    {
      "id": "finding_04",
      "type": "strength",
      "location": "Across the material",
      "title": "The core skills receive balanced practice",
      "evidence": "Fractions, proportional relationships and signed numbers each receive practice, with a mix of calculation and reasoning questions"
    }
  ]
}

The complete response also includes schemaVersion, engineVersion, policyVersion, completedAt and the native report used by the Steletta interface.

Review units

The accepted job includes usage.estimatedUnitsMilli. Steletta calculates this deterministic estimate at upload time from the source's length and visual load; the review model never chooses the charge. PDF estimates include a front-matter allowance so a normal decorative cover does not move an otherwise identical resource into a higher tier. One review unit is 1000 milli-units. The completed job records the settled amount in usage.finalUnitsMilli. Units are charged only after a successful review; failed and cancelled reviews charge zero units.

Review a catalog

Create one review per resource and keep your own stable resourceId and version beside the returned review ID. This preserves traceability and lets an unchanged retry reuse the original job.

[
  {
    "resourceId": "catalog-1042",
    "version": "v3",
    "file": "./assessments/geometry.pdf",
    "purpose": "Listing title and description…",
    "grade": "Grade 5"
  },
  {
    "resourceId": "catalog-1043",
    "version": "v1",
    "file": "./assessments/reading.pdf",
    "purpose": "Intended use and learning goals…",
    "grade": "Grade 4"
  }
]

The integration runner accepts manifests of up to 10,000 resources and keeps two complete review pipelines in flight at a time. It records accepted IDs immediately, then collects each completed result without flooding the admission queue.

Authentication and scopes

API keys identify an organization, environment and integration. They are separate from the user sessions that identify people in the Steletta workspace.

  • Store keys in a server-side secret manager and never expose them in browser code.
  • Create separate test and live keys for separate systems.
  • Grant only the required scopes, such as reviews:read, reviews:write or usage:read.
  • A resource owned by another organization returns the same 404 response as a missing resource.

Idempotency

Every review submission requires an Idempotency-Key. Repeating the same key with identical source bytes and parameters returns the original job. Reusing it with different inputs returns 409 idempotency_conflict, preventing duplicate work and billing.

Use a key derived from your resource ID and version. When the resource changes, increment the version and use a new key.

Webhooks

Integration available on request. Custom webhook integrations are scoped and built for your workflow; a one-time implementation fee may apply, quoted separately. Contact Steletta to discuss your requirements.

Use GET /reviews/{reviewId} to poll review status without a webhook integration.

Privacy and retention

Uploaded source files are private and temporary. They become eligible for deletion after a review completes, permanently fails or is cancelled once outstanding upload access ends. Unfinished sources are scheduled for deletion no later than 24 hours after upload begins.

Temporary result storage

Set retainReport=false in a multipart review submission or retainReport: false when preparing a direct upload. The completed result remains available for 24 hours, then result requests return HTTP 410 and its report payload is scheduled for deletion.

Use DELETE /reviews/{reviewId} after safely storing a completed result to remove it earlier. A review cannot be deleted while it is processing. Necessary usage and operational records remain. See Privacy for the complete policy.

Errors and retries

Immediate HTTP errors contain a stable machine-readable code, a safe message and a request ID for support correlation.

{
  "error": {
    "code": "invalid_api_key",
    "message": "The supplied API key is invalid.",
    "requestId": "req_01J..."
  }
}

Retry HTTP 429 and 503 after the supplied Retry-After delay. For network failures, use exponential backoff with jitter and preserve the original idempotency key. Do not automatically retry non-idempotent management operations.

Review processing failures

A failed or automatically requeued review exposes a separate error object from GET /reviews/{reviewId}. Its code is stable, its message is safe to show to a customer, and failed reviews do not consume review units.

{
  "id": "rev_01J...",
  "status": "failed",
  "error": {
    "code": "provider_rate_limited",
    "message": "OpenAI is temporarily busy, so this review could not complete. No review units were charged. Try again in a few minutes.",
    "retryScheduled": false,
    "reviewUnitsChargedMilli": 0
  }
}

If retryScheduled is true, Steletta has already queued one bounded automatic retry. Keep polling the same review ID. If it is false, wait briefly and submit a new review with a new idempotency key.

Rate limits and admission

Steletta applies per-organization request, upload and pending-work limits to keep one integration from delaying another. A limit response uses HTTP 429, includes a stable error code and supplies Retry-After. Wait for that delay and add jitter. Preserve the original idempotency key when retrying a review submission; do not automatically retry non-idempotent management operations.

quota_exhausted means the active agreement lacks enough review units for the estimated resource. queue_capacity means too many files or bytes are currently pending; retry after existing reviews finish. Neither response starts model work or charges review units.

Endpoints

POST/uploads

Prepare Upload · reviews:write

POST/uploads/{uploadId}/complete

Complete Upload · reviews:write

GET/health

Get Health

GET/reviews

List Reviews · reviews:read

POST/reviews

Create Review · reviews:write

GET/reviews/{reviewId}

Get Review · reviews:read

DELETE/reviews/{reviewId}

Delete Review · reviews:write

GET/reviews/{reviewId}/result

Get Review Result · reviews:read

POST/reviews/{reviewId}/cancel

Cancel Review · reviews:write

GET/usage

Get Usage · usage:read

GET/organization

Get Organization · members:read

GET/members

List Members · members:read

POST/members

Invite Member · members:write

DELETE/members/{memberId}

Revoke Member · members:write

GET/api-keys

List Api Keys · keys:read

POST/api-keys

Create Api Key · keys:write

DELETE/api-keys/{apiKeyId}

Revoke Api Key · keys:write

POST/api-keys/{apiKeyId}/rotate

Rotate Api Key · keys:write

Versions

The URL version controls the HTTP contract. Every completed result also records the result schema, review engine and policy versions used to produce it. Treat new response fields as additive and retain these versions with the result for reproducibility.