This file defines the current v1 contract for the Week 1 vertical slice and matches the implementation in backend/project/api_views.py.
cogflow-platformAPI:http://127.0.0.1:8000cogflow-builder-applocal UI: typicallyhttp://127.0.0.1:5500(VS Code Live Server)cogflow-interpreter-applocal UI: usehttp://127.0.0.1:5501when running side-by-side (or:5500when run alone)
Builder and Interpreter call the API on port 8000 (as shown in frontend/builder/publish_stub.html and frontend/interpreter/runtime_stub.html).
- Live schema endpoint:
GET /api/schema - Name in Django URLs:
openapi-schema - JSON output uses DRF's built-in OpenAPI generator.
Generate a checked-in schema artifact:
cd /home/kamisalibayeva/GitHub/cogflow-platform
docker compose exec -T api python manage.py generateschema --format openapi-json > docs/openapi.jsonopenapi: 3.0.3
info:
title: CogFlow Platform API
version: 1.0.0-day3
description: |
Day 3 contract-first API for the Week 1 vertical slice.
Covers publish, start-run, submit-result, studies list, and health.
servers:
- url: http://127.0.0.1:8000
description: Local Docker compose API
- url: http://localhost:8000
description: Local Docker compose API (alt hostname)
tags:
- name: Ops
- name: Auth
- name: Studies
- name: Builder
- name: Interpreter
paths:
/healthz:
get:
tags: [Ops]
summary: Service health check
responses:
'200':
description: Service is healthy
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
example: true
required: [ok]
/api/v1/studies:
get:
tags: [Studies]
summary: List studies visible in portal
responses:
'200':
description: Studies list
content:
application/json:
schema:
$ref: '#/components/schemas/StudiesListResponse'
/api/v1/auth/login:
post:
tags: [Auth]
summary: Session login for platform users
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AuthLoginRequest'
responses:
'200':
description: Login succeeded
content:
application/json:
schema:
$ref: '#/components/schemas/AuthLoginResponse'
'401':
description: Invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
/api/v1/auth/logout:
post:
tags: [Auth]
summary: Logout current session
responses:
'200':
description: Logout succeeded
/api/v1/auth/mfa/setup:
post:
tags: [Auth]
summary: Generate TOTP setup secret and provisioning URI for authenticated user
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/TotpSetupRequest'
responses:
'200':
description: Setup data returned
content:
application/json:
schema:
$ref: '#/components/schemas/TotpSetupResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
/api/v1/auth/mfa/verify:
post:
tags: [Auth]
summary: Verify TOTP code and mark MFA verified in current session
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TotpVerifyRequest'
responses:
'200':
description: TOTP verification succeeded
content:
application/json:
schema:
$ref: '#/components/schemas/TotpVerifyResponse'
'401':
description: Invalid code or not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
'400':
description: TOTP not set up
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
/api/v1/configs/publish:
post:
tags: [Builder]
summary: Publish a Builder config and upsert study linkage
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PublishConfigRequest'
responses:
'201':
description: Config accepted and study linkage upserted
content:
application/json:
schema:
$ref: '#/components/schemas/PublishConfigResponse'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/api/v1/runs/start:
post:
tags: [Interpreter]
summary: Start a run session for a published study
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/StartRunRequest'
responses:
'201':
description: Run session created
content:
application/json:
schema:
$ref: '#/components/schemas/StartRunResponse'
'400':
description: Validation error or no published config
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ValidationError'
- $ref: '#/components/schemas/ErrorMessage'
'404':
description: Study not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
/api/v1/results/submit:
post:
tags: [Interpreter]
summary: Submit aggregate and optional per-trial result payloads
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SubmitResultRequest'
responses:
'201':
description: Result stored
content:
application/json:
schema:
$ref: '#/components/schemas/SubmitResultResponse'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
'404':
description: Run session not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
/api/v1/results/decrypt:
post:
tags: [Interpreter]
summary: Protected decrypt/read endpoint for stored result payloads
description: |
Requires authenticated user session and successful TOTP verification.
Decrypt access is denied unless MFA is enabled and verified within the
configured `MFA_REAUTH_SECONDS` window.
All denied and successful decrypt attempts are recorded in `AuditEvent`.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DecryptResultRequest'
responses:
'200':
description: Decrypted payload returned
content:
application/json:
schema:
$ref: '#/components/schemas/DecryptResultResponse'
'403':
description: MFA verification required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
'404':
description: Run session or result envelope not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
components:
schemas:
RuntimeMode:
type: string
enum: [django, jatos, hybrid, home_gear_lsl]
RunStatus:
type: string
enum: [completed, failed]
ErrorMessage:
type: object
properties:
error:
type: string
required: [error]
ValidationError:
type: object
additionalProperties: true
description: DRF validation error object keyed by field name.
AuthLoginRequest:
type: object
required: [username, password]
properties:
username:
type: string
password:
type: string
AuthLoginResponse:
type: object
properties:
ok:
type: boolean
username:
type: string
mfa_enabled:
type: boolean
required: [ok, username, mfa_enabled]
TotpSetupRequest:
type: object
properties:
regenerate:
type: boolean
default: false
TotpSetupResponse:
type: object
properties:
ok:
type: boolean
username:
type: string
totp_secret:
type: string
otpauth_uri:
type: string
required: [ok, username, totp_secret, otpauth_uri]
TotpVerifyRequest:
type: object
required: [code]
properties:
code:
type: string
TotpVerifyResponse:
type: object
properties:
ok:
type: boolean
username:
type: string
mfa_enabled:
type: boolean
mfa_verified_at:
type: string
format: date-time
required: [ok, username, mfa_enabled, mfa_verified_at]
PublishConfigRequest:
type: object
required:
- study_slug
- study_name
- config_version_label
- config
properties:
study_slug:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
example: attention-battery-pilot
study_name:
type: string
maxLength: 255
example: Attention Battery Pilot
config_version_label:
type: string
maxLength: 50
example: v1
builder_version:
type: string
maxLength: 50
example: 2026.03.13
runtime_mode:
$ref: '#/components/schemas/RuntimeMode'
config:
type: object
additionalProperties: true
PublishConfigResponse:
type: object
properties:
study_id:
type: integer
example: 12
config_version_id:
type: integer
example: 54
study_slug:
type: string
example: attention-battery-pilot
dashboard_url:
type: string
example: /portal/studies/attention-battery-pilot
required: [study_id, config_version_id, study_slug, dashboard_url]
StartRunRequest:
type: object
required: [study_slug]
properties:
study_slug:
type: string
example: attention-battery-pilot
participant_external_id:
type: string
nullable: true
example: participant-001
StartRunResponse:
type: object
properties:
run_session_id:
type: string
format: uuid
study_slug:
type: string
config_version_id:
type: integer
config:
type: object
additionalProperties: true
participant_key:
type: string
description: Salted SHA-256 pseudonym key.
required: [run_session_id, study_slug, config_version_id, config, participant_key]
TrialPayload:
type: object
additionalProperties: true
description: Arbitrary task-specific trial data.
SubmitResultRequest:
type: object
required:
- run_session_id
- status
- trial_count
- result_payload
properties:
run_session_id:
type: string
format: uuid
status:
$ref: '#/components/schemas/RunStatus'
trial_count:
type: integer
minimum: 0
example: 240
result_summary:
type: object
additionalProperties: true
result_payload:
type: object
additionalProperties: true
trials:
type: array
items:
$ref: '#/components/schemas/TrialPayload'
default: []
SubmitResultResponse:
type: object
properties:
run_session_id:
type: string
format: uuid
status:
type: string
stored:
type: boolean
example: true
trial_records_stored:
type: integer
minimum: 0
example: 240
required: [run_session_id, status, stored, trial_records_stored]
DecryptResultRequest:
type: object
required: [run_session_id]
properties:
run_session_id:
type: string
format: uuid
include_trials:
type: boolean
default: false
DecryptResultResponse:
type: object
properties:
run_session_id:
type: string
format: uuid
study_slug:
type: string
status:
type: string
result_payload:
type: object
additionalProperties: true
trials:
nullable: true
oneOf:
- type: array
items:
type: object
additionalProperties: true
- type: 'null'
required: [run_session_id, study_slug, status, result_payload, trials]
StudyListItem:
type: object
properties:
study_slug:
type: string
study_name:
type: string
runtime_mode:
$ref: '#/components/schemas/RuntimeMode'
latest_config_version:
type: string
nullable: true
run_count:
type: integer
minimum: 0
last_result_at:
type: string
format: date-time
nullable: true
last_activity_at:
type: string
format: date-time
dashboard_url:
type: string
required:
- study_slug
- study_name
- runtime_mode
- latest_config_version
- run_count
- last_result_at
- last_activity_at
- dashboard_url
StudiesListResponse:
type: object
properties:
studies:
type: array
items:
$ref: '#/components/schemas/StudyListItem'
required: [studies]POST /api/v1/configs/publishis upsert-safe bystudy_slugandconfig_version_label.POST /api/v1/runs/startusesstudy_slug(notstudy_id) in v1.POST /api/v1/results/submitsupports optionaltrials[]for per-trial persistence.POST /api/v1/results/decryptrequires user session auth + TOTP MFA verification.- Day 3 and onward endpoints are covered by integration tests in
backend/project/tests/test_day3_api_contract.pyandbackend/project/tests/test_day4_integration.py.