Skip to content

Latest commit

 

History

History
502 lines (374 loc) · 13.3 KB

File metadata and controls

502 lines (374 loc) · 13.3 KB

Backend API Reference

This document describes the backend HTTP surface mounted by the current Express application.

Base URL in local Docker development: http://localhost:4000

Primary router entrypoints:

Response Conventions

  • Validation failures generally return 400 with an error field and often details
  • Auth failures are usually 401
  • Ownership or existence failures are usually 404
  • State conflicts are usually 409
  • Unsupported preview or file types are usually 415
  • Unhandled server failures return 500

Service And Monitoring

GET /

  • Auth: none
  • Purpose: basic service metadata
  • Response 200:
{ "service": "integricode-backend", "status": "running" }

GET /health

  • Auth: none
  • Purpose: compact health probe for API process and dependencies
  • Response: 200 for ok or degraded, 503 for error
  • Shape:
{
  "status": "ok",
  "checks": {
    "database": { "status": "ok" },
    "reports": { "status": "ok" },
    "storage": { "status": "ok" }
  }
}

GET /api/status

  • Auth: none
  • Purpose: detailed monitoring payload for diagnostics
  • Response: 200 for ok or degraded, 503 for error
  • Notes:
    • includes database, report runner, and storage details
    • includes summary fields for degradation reasons and recent report failures

Auth

Mounted at /api/auth

POST /api/auth/check-email

  • Auth: none
  • Purpose: check whether an auth email is available
  • Request body:
{ "email": "jane@example.edu" }
  • Response 200:
{ "available": true }
  • Errors:
    • 400 invalid email address
    • 500 failed lookup

ALL /api/auth/*

  • Auth: handled by Better Auth
  • Purpose: session and auth endpoints delegated to better-auth
  • Notes:
    • mounted via toNodeHandler(auth)
    • exact endpoint set depends on Better Auth configuration

Public Student Submission APIs

Mounted at /api/v1/submissions

GET /api/v1/submissions/crypto-config

  • Auth: none
  • Purpose: expose the public RSA config used by submission clients
  • Response 200:
{
  "kid": "dev-kid-1",
  "alg": "RSA-OAEP-256",
  "publicKeyJwk": { "kty": "RSA", "n": "...", "e": "AQAB" },
  "expiresAt": "2026-04-09T12:00:00.000Z"
}

GET /api/v1/submissions/policy

  • Auth: none
  • Purpose: return the active submission/privacy policy
  • Errors:
    • 503 no active policy configured
    • 500 failed policy lookup

POST /api/v1/submissions

  • Auth: none
  • Purpose: create a student submission
  • Content type: multipart/form-data
  • Required multipart fields:
    • assignmentKey
    • submitterEncrypted
    • submitterEncryption
    • file
  • Optional multipart fields:
    • submissionTextBase64
  • Important behaviors:
    • rate limited
    • temporary abuse blocks can be applied after repeated invalid requests
    • HTTPS is enforced in production
    • file upload hard-limit is 5 MB at the route layer
  • Success 201:
{
  "submissionId": "uuid",
  "submissionPublicKey": "uuid",
  "assignmentId": "uuid",
  "submittedAt": "2026-04-08T12:00:00.000Z",
  "expiresAt": "2026-05-08T12:00:00.000Z"
}
  • Common errors:
    • 400 invalid multipart payload, invalid JSON fields, invalid encryption payload
    • 401 policy acknowledgement required
    • 404 assignment key invalid
    • 409 policy version mismatch or resubmission blocked
    • 410 assignment due window closed
    • 413 file too large
    • 415 unsupported file type or archive contents
    • 429 rate limit or temporary abuse block
    • 503 no active privacy policy configured

GET /api/v1/submissions/:submissionPublicKey/status

  • Auth: none
  • Purpose: confirm submission status using the public confirmation key
  • Response 200:
{
  "submission": {
    "submissionId": "uuid",
    "submissionPublicKey": "uuid",
    "assignmentId": "uuid",
    "submittedAt": "2026-04-08T12:00:00.000Z",
    "expiresAt": "2026-05-08T12:00:00.000Z",
    "status": "active"
  }
}
  • Errors:
    • 400 invalid public key format
    • 404 submission not found

Instructor Profile And Billing APIs

Mounted at /api/v1/instructors

All routes in this section require a valid authenticated session via requireAuth.

GET /api/v1/instructors/me

  • Purpose: fetch current instructor profile
  • Response 200:
{
  "instructor": {
    "instructor_id": "uuid",
    "name": "Jane Doe",
    "email": "jane@example.edu",
    "institution": "University of Example"
  }
}
  • Errors:
    • 404 instructor record not found
    • 500 failed lookup

PATCH /api/v1/instructors/me

  • Purpose: update current instructor profile and sync the Better Auth user row
  • Request body fields:
    • name
    • email
    • institution
  • Notes:
    • validates with Zod
    • email conflicts return 409
  • Errors:
    • 400 invalid body
    • 404 instructor not found
    • 409 email already in use
    • 500 auth-user sync or update failure

GET /api/v1/instructors/me/notifications

  • Purpose: fetch instructor notification preferences

PATCH /api/v1/instructors/me/notifications

  • Purpose: update instructor notification preferences
  • Errors:
    • 400 invalid body
    • 500 update failure

POST /api/v1/instructors/me/notifications/test-email

  • Purpose: send a test notification email
  • Errors:
    • 400 invalid body or missing notification email
    • 503 email service not configured
    • 500 send failure

GET /api/v1/instructors/me/billing/

  • Purpose: fetch instructor billing profile and related billing view data

POST /api/v1/instructors/me/billing/portal-session

  • Purpose: create a Stripe billing portal session
  • Errors:
    • 404 no billing customer found
    • 500 portal session creation failed

Instructor Assignment, Submission Review, Upload, And Report APIs

Mounted at /api/v1/instructor

All routes in this section require a valid authenticated session via requireAuth.

Assignments

POST /api/v1/instructor/assignments

  • Purpose: create an assignment for the authenticated instructor
  • Success 201: returns the assignment payload
  • Errors:
    • 400 invalid body
    • 409 unique assignment-key generation failed
    • 500 creation failure

GET /api/v1/instructor/assignments

  • Purpose: list assignments owned by the authenticated instructor

GET /api/v1/instructor/assignments/:assignmentId

  • Purpose: fetch one instructor-owned assignment
  • Errors:
    • 400 invalid assignment ID
    • 404 assignment not found

DELETE /api/v1/instructor/assignments/:assignmentId

  • Purpose: delete an instructor-owned assignment
  • Success 204
  • Errors:
    • 400 invalid assignment ID
    • 404 assignment not found

Submission Review

GET /api/v1/instructor/assignments/:assignmentId/submissions

  • Purpose: list submissions for an assignment
  • Errors:
    • 400 invalid assignment ID or query
    • 404 assignment not found

GET /api/v1/instructor/assignments/:assignmentId/submissions/:submissionId

  • Purpose: fetch submission detail for instructor review
  • Errors:
    • 400 invalid IDs
    • 404 submission not found

GET /api/v1/instructor/assignments/:assignmentId/submissions/:submissionId/content

  • Purpose: fetch previewable submission content
  • Errors:
    • 400 invalid IDs
    • 404 assignment or submission not found
    • 415 preview unsupported for the stored file type

GET /api/v1/instructor/assignments/:assignmentId/submissions/:submissionId/download

  • Purpose: download the stored submission artifact
  • Response: binary download
  • Errors:
    • 400 invalid IDs
    • 404 submission not found

GET /api/v1/instructor/assignments/:assignmentId/submissions/:submissionId/events

  • Purpose: list submission event history
  • Errors:
    • 400 invalid IDs
    • 404 submission not found

Historical Uploads And Export

POST /api/v1/instructor/assignments/:assignmentId/uploads

  • Purpose: upload historical comparison data for an assignment
  • Content type: multipart/form-data
  • Success 201:
{ "upload": { "upload_id": "uuid" } }
  • Errors:
    • 400 invalid upload request
    • 404 assignment not found
    • 413 file exceeds configured max
    • 415 unsupported file type or archive contents

GET /api/v1/instructor/assignments/:assignmentId/uploads

  • Purpose: list historical uploads for an assignment

GET /api/v1/instructor/assignments/:assignmentId/uploads/:uploadId/download

  • Purpose: download one historical upload artifact
  • Response: binary download

DELETE /api/v1/instructor/assignments/:assignmentId/uploads/:uploadId

  • Purpose: delete one historical upload
  • Success 204
  • Errors:
    • 400 invalid IDs
    • 404 upload not found
    • 409 upload is referenced by an in-progress report

GET /api/v1/instructor/assignments/:assignmentId/export

  • Purpose: stream a ZIP export for an assignment
  • Response: application/zip
  • Errors:
    • 400 invalid assignment ID
    • 404 assignment not found
    • 500 export artifact missing or export failed

Reports

POST /api/v1/instructor/assignments/:assignmentId/reports

  • Purpose: queue a report run for an assignment
  • Success 202: returns the queued report payload
  • Notable request concepts:
    • optional historical upload IDs
    • optional exclusion upload IDs
    • optional similarity threshold override
  • Errors:
    • 400 invalid assignment/body, not enough eligible inputs, invalid uploads
    • 404 assignment not found
    • 409 report already in progress
    • 500 required artifacts missing from storage

GET /api/v1/instructor/assignments/:assignmentId/reports

  • Purpose: list reports for an assignment

GET /api/v1/instructor/assignments/:assignmentId/reports/latest

  • Purpose: fetch the latest report for an assignment
  • Errors:
    • 400 invalid assignment ID
    • 404 assignment or report not found

GET /api/v1/instructor/assignments/:assignmentId/reports/:reportId

  • Purpose: fetch one report by ID
  • Notes:
    • route-level response shape comes from report service output
    • public-facing report status is normalized to in-progress | complete | failed

GET /api/v1/instructor/assignments/:assignmentId/report-inputs/:reportInputId/content

  • Purpose: preview a report input's source content
  • Errors:
    • 400 invalid IDs
    • 404 assignment, report input, submission, historical upload, or source text not found
    • 415 preview unsupported
    • 500 historical upload artifact missing

GET /api/v1/instructor/assignments/:assignmentId/reports/:reportId/pairs/:pairId

  • Purpose: fetch detailed pair comparison data for one report pair
  • Errors:
    • 400 invalid IDs
    • 404 assignment, report, or pair not found
    • 415 preview unavailable for the requested pair/input mix

Stripe APIs

Mounted at /api/v1/stripe

Auth Behavior

  • POST /webhook is intentionally unauthenticated
  • all other Stripe routes perform session lookup inside Stripe middleware
  • most authenticated Stripe routes also require verified email
  • POST /create-checkout-session and POST /verify-session allow unverified authenticated users

GET /api/v1/stripe/plans

  • Auth: none
  • Purpose: list active billing plans

GET /api/v1/stripe/subscription

  • Auth: authenticated session
  • Purpose: fetch the current user's subscription and billing details

POST /api/v1/stripe/create-checkout-session

  • Auth: authenticated session
  • Purpose: create a hosted Stripe checkout session for pro or enterprise
  • Errors:
    • 400 invalid body, invalid plan, or user already has an active subscription
    • 500 checkout creation failed

POST /api/v1/stripe/change-plan

  • Auth: authenticated session with verified email
  • Purpose: switch an active subscription to another plan
  • Errors:
    • 400 invalid body, invalid plan, or already on requested plan
    • 404 no active subscription found
    • 500 Stripe or local sync failure

POST /api/v1/stripe/cancel-subscription

  • Auth: authenticated session with verified email
  • Purpose: set cancel_at_period_end on the current subscription
  • Errors:
    • 404 no active subscription found
    • 500 cancellation failed

POST /api/v1/stripe/reactivate-subscription

  • Auth: authenticated session with verified email
  • Purpose: remove scheduled cancellation for the current subscription
  • Errors:
    • 404 no subscription found
    • 500 reactivation failed

POST /api/v1/stripe/verify-session

  • Auth: authenticated session
  • Purpose: verify a checkout session after redirect and return Stripe-side outcome details
  • Errors:
    • 400 invalid body or payment not completed
    • 500 verification failed

POST /api/v1/stripe/webhook

  • Auth: none
  • Purpose: receive Stripe webhook events and synchronize local billing state
  • Body handling:
    • must use the raw request body for signature verification
    • signature comes from the stripe-signature header
  • Common outcomes:
    • checkout.session.completed updates billing details and activates pending subscriptions
    • invoice.payment_succeeded creates payment records
    • invoice.payment_failed marks subscriptions past_due and records failed payments
    • customer.subscription.updated syncs local subscription state
    • customer.subscription.deleted marks subscriptions canceled
  • Errors:
    • 400 signature verification failure or missing required metadata
    • 500 webhook processing failure