/api/v1/account/status
Account status and remaining credits
API & integrations
Connect marking, integrity checks and learner analytics to your LMS or MIS. One key covers the full REST surface; sandbox keys return mocks and never charge credits.
Base URL https://feedbackflows.org/api/v1 · Header X-API-Key
This is one long page on purpose — so you can copy the whole hub into an AI chat when you are vibe-coding and want all the API context in one go.
The same API powers marking in the product, integrity tools, roster sync and result export. Pick a capability, then jump to the reference or a live tester.
Queue rubric marking, automarking, smart essays, exam scripts, media and interactive feedback — then pull results back when the job finishes.
/rubric-marking/jobs · /automarking/jobs · /smart-essay/jobs
Run AI writing detection, style comparison and reference checks so integrity sits alongside marking in your own workflows.
/ai-detector/jobs · /style-comparison · /reference-check/jobs
Read learner progress and class assignment analysis for dashboards, MIS reports or tutor follow-up.
/students/…/progress-report · /classes/…/assignments/…/analyze
Sync a roster from your LMS, push assignment outcomes out, and keep Feedback Flows aligned with your MIS.
/students · /classes/…/students · /classes/…/results
List and read students, classes, rubrics and submissions that your key is allowed to see.
/students · /classes · /rubrics
Estimate cost, submit async work, poll status, or receive a signed callback_url when a job completes.
/jobs/estimate-cost · /webhooks/test
Access is keyed and scoped. Sandbox keys are safe for exploration; live keys spend credits on the same jobs you run in the product.
API access is turned on per account. Once approved, create keys under Settings → Integrations. Team members ask their owner to request access or create keys.
Sign in to manage keys Request API accessOrganisation keys live in the Enterprise portal under Integrations. Owners and managers with the API capability create sandbox or live keys for shared credit pools.
For organisations Talk to usmarking, integrity and analytics. Add media or admin when you need them.X-API-Key on every request. Async POSTs accept an Idempotency-Key header.When you are ready to integrate, follow this path.
GET /me to confirm scopes and remaining rate limits.POST /jobs/estimate-cost before you queue work.callback_url.Send X-API-Key on every request. Default scopes are marking, integrity and analytics. Add media or admin when you need them. Sync calls are 60/minute; job submissions are 10/hour. Async POSTs accept an Idempotency-Key header.
curl https://feedbackflows.org/api/v1/me \ -H "X-API-Key: $FEEDBACKFLOWS_API_KEY"
import os, requests
r = requests.get(
"https://feedbackflows.org/api/v1/me",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
)
print(r.json())
Runs against this origin. Use a sandbox key so nothing is billed. The dropdown is built from the live OpenAPI spec.
Quick testers (including the older “v2” URLs) still call /api/v1. Dedicated pages are useful for file uploads and polling.
Generated from the live routing table. Search filters this list.
No endpoints match that search.
/api/v1/account/status
Account status and remaining credits
/api/v1/me
Current API key, scopes and remaining rate limits
/api/v1/openapi.json
This document (no API key required)
/api/v1/stats/users
Total user count (requires an admin-owned key)
/api/v1/test
Validate API key
/api/v1/ai-tutor
Formative tutor feedback on a draft
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
student_draft |
string | yes |
mode |
string | no |
marking_rubric |
string | no |
persona |
string | no |
curl -X POST https://feedbackflows.org/api/v1/ai-tutor \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"student_draft": "example",
"mode": "general",
"marking_rubric": "example",
"persona": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/ai-tutor",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"student_draft": "example",
"mode": "general",
"marking_rubric": "example",
"persona": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/ai-tutor", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"student_draft": "example",
"mode": "general",
"marking_rubric": "example",
"persona": "example"
}),
});
/api/v1/interactive-feedback
Inline feedback against a list of criteria
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
student_text |
string | yes |
marking_criteria |
array | yes |
curl -X POST https://feedbackflows.org/api/v1/interactive-feedback \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"student_text": "example",
"marking_criteria": [
"Clarity"
]
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/interactive-feedback",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"student_text": "example",
"marking_criteria": [
"Clarity"
]
},
)
await fetch("https://feedbackflows.org/api/v1/interactive-feedback", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"student_text": "example",
"marking_criteria": [
"Clarity"
]
}),
});
/api/v1/smart-essay-marker
Mark one essay against criteria (synchronous) (deprecated)
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
essay_text |
string | yes |
marking_criteria |
array | yes |
curl -X POST https://feedbackflows.org/api/v1/smart-essay-marker \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"essay_text": "example",
"marking_criteria": [
"Clarity"
]
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/smart-essay-marker",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"essay_text": "example",
"marking_criteria": [
"Clarity"
]
},
)
await fetch("https://feedbackflows.org/api/v1/smart-essay-marker", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"essay_text": "example",
"marking_criteria": [
"Clarity"
]
}),
});
/api/v1/students/{student_id}/worksheet
Generate a targeted practice worksheet
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
weaknesses_list |
array | no |
format |
string | no |
level |
string | no |
num_questions |
integer | no |
curl -X POST https://feedbackflows.org/api/v1/students/{student_id}/worksheet \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"weaknesses_list": [
"Clarity"
],
"format": "example",
"level": "example",
"num_questions": 1
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/students/{student_id}/worksheet",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"weaknesses_list": [
"Clarity"
],
"format": "example",
"level": "example",
"num_questions": 1
},
)
await fetch("https://feedbackflows.org/api/v1/students/{student_id}/worksheet", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"weaknesses_list": [
"Clarity"
],
"format": "example",
"level": "example",
"num_questions": 1
}),
});
/api/v1/ai-detector
Hybrid AI detector (synchronous, detailed response) (deprecated)
Requires the `integrity` scope.
| Body field | Type | Required |
|---|---|---|
document_text |
string | yes |
academic_mode |
boolean | no |
curl -X POST https://feedbackflows.org/api/v1/ai-detector \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"document_text": "example",
"academic_mode": false
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/ai-detector",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"document_text": "example",
"academic_mode": false
},
)
await fetch("https://feedbackflows.org/api/v1/ai-detector", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"document_text": "example",
"academic_mode": false
}),
});
/api/v1/full-reference-check
Bibliography and citation checker
Requires the `integrity` scope.
| Body field | Type | Required |
|---|---|---|
document_text |
string | yes |
style |
string | no |
enable_semantic_check |
boolean | no |
curl -X POST https://feedbackflows.org/api/v1/full-reference-check \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"document_text": "example",
"style": "APA",
"enable_semantic_check": false
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/full-reference-check",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"document_text": "example",
"style": "APA",
"enable_semantic_check": false
},
)
await fetch("https://feedbackflows.org/api/v1/full-reference-check", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"document_text": "example",
"style": "APA",
"enable_semantic_check": false
}),
});
/api/v1/reference-check
Legacy AI detector (simplified response) (deprecated)
Requires the `integrity` scope.
| Body field | Type | Required |
|---|---|---|
document_text |
string | yes |
curl -X POST https://feedbackflows.org/api/v1/reference-check \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"document_text": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/reference-check",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"document_text": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/reference-check", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"document_text": "example"
}),
});
/api/v1/style-comparison
Compare one submission against a student's writing samples
Requires the `integrity` scope.
| Body field | Type | Required |
|---|---|---|
student_id |
integer | yes |
submission_text |
string | yes |
curl -X POST https://feedbackflows.org/api/v1/style-comparison \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"student_id": 1,
"submission_text": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/style-comparison",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"student_id": 1,
"submission_text": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/style-comparison", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"student_id": 1,
"submission_text": "example"
}),
});
/api/v1/ai-detector/jobs
Queue AI detection (preferred over the synchronous endpoint)
Requires one of the following scopes: `integrity` or `marking`.
| Body field | Type | Required |
|---|---|---|
document_text |
string | yes |
academic_mode |
boolean | no |
callback_url |
string | no |
curl -X POST https://feedbackflows.org/api/v1/ai-detector/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"document_text": "example",
"academic_mode": false,
"callback_url": "https://example.com/webhooks/feedbackflows"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/ai-detector/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"document_text": "example",
"academic_mode": false,
"callback_url": "https://example.com/webhooks/feedbackflows"
},
)
await fetch("https://feedbackflows.org/api/v1/ai-detector/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"document_text": "example",
"academic_mode": false,
"callback_url": "https://example.com/webhooks/feedbackflows"
}),
});
/api/v1/ai-detector/jobs/{job_id}
AI detection job status and results
Requires one of the following scopes: `integrity` or `marking`.
/api/v1/ai-detector/jobs/{job_id}/cancel
Cancel an AI detector job and refund unused credits
Requires one of the following scopes: `integrity` or `marking`.
/api/v1/ai-tutor/jobs
Queue AI tutor feedback
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
student_draft |
string | yes |
mode |
string | no |
marking_rubric |
string | no |
persona |
string | no |
callback_url |
string | no |
curl -X POST https://feedbackflows.org/api/v1/ai-tutor/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"student_draft": "example",
"mode": "example",
"marking_rubric": "example",
"persona": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/ai-tutor/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"student_draft": "example",
"mode": "example",
"marking_rubric": "example",
"persona": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/ai-tutor/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"student_draft": "example",
"mode": "example",
"marking_rubric": "example",
"persona": "example"
}),
});
/api/v1/ai-tutor/jobs/{job_id}
AI tutor job status and result
Requires the `marking` scope.
/api/v1/ai-tutor/jobs/{job_id}/cancel
Cancel an AI tutor job and refund unused credits
Requires the `marking` scope.
/api/v1/automarking/jobs
Queue question-by-question automarking
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
zip_base64 |
string | yes |
question_template_id |
integer | no |
questions |
array | no |
mark_mode |
string | no |
filename |
string | no |
callback_url |
string | no |
credit_check_only |
boolean | no |
curl -X POST https://feedbackflows.org/api/v1/automarking/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"zip_base64": "UEsDBBQAAAAA",
"question_template_id": 1,
"questions": [],
"mark_mode": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/automarking/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"zip_base64": "UEsDBBQAAAAA",
"question_template_id": 1,
"questions": [],
"mark_mode": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/automarking/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"zip_base64": "UEsDBBQAAAAA",
"question_template_id": 1,
"questions": [],
"mark_mode": "example"
}),
});
/api/v1/automarking/jobs/{job_id}
Automarking job status, progress and results
Requires the `marking` scope.
/api/v1/automarking/jobs/{job_id}/cancel
Cancel an automarking or exam-marker job and refund unused credits
Requires the `marking` scope.
/api/v1/batch-style/jobs
Queue a batch style comparison
Requires the `integrity` scope.
| Body field | Type | Required |
|---|---|---|
zip_base64 |
string | yes |
filename |
string | no |
callback_url |
string | no |
credit_check_only |
boolean | no |
curl -X POST https://feedbackflows.org/api/v1/batch-style/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"zip_base64": "UEsDBBQAAAAA",
"filename": "example",
"callback_url": "https://example.com/webhooks/feedbackflows",
"credit_check_only": false
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/batch-style/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"zip_base64": "UEsDBBQAAAAA",
"filename": "example",
"callback_url": "https://example.com/webhooks/feedbackflows",
"credit_check_only": false
},
)
await fetch("https://feedbackflows.org/api/v1/batch-style/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"zip_base64": "UEsDBBQAAAAA",
"filename": "example",
"callback_url": "https://example.com/webhooks/feedbackflows",
"credit_check_only": false
}),
});
/api/v1/batch-style/jobs/{job_id}
Batch style job status and comparisons
Requires the `integrity` scope.
/api/v1/batch-style/jobs/{job_id}/cancel
Cancel a batch style job
Requires the `integrity` scope.
/api/v1/exam-marker/jobs
Queue exam script marking for one student
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
student_id |
integer | yes |
zip_base64 |
string | yes |
filename |
string | no |
callback_url |
string | no |
curl -X POST https://feedbackflows.org/api/v1/exam-marker/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"student_id": 1,
"zip_base64": "UEsDBBQAAAAA",
"filename": "example",
"callback_url": "https://example.com/webhooks/feedbackflows"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/exam-marker/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"student_id": 1,
"zip_base64": "UEsDBBQAAAAA",
"filename": "example",
"callback_url": "https://example.com/webhooks/feedbackflows"
},
)
await fetch("https://feedbackflows.org/api/v1/exam-marker/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"student_id": 1,
"zip_base64": "UEsDBBQAAAAA",
"filename": "example",
"callback_url": "https://example.com/webhooks/feedbackflows"
}),
});
/api/v1/exam-marker/jobs/{job_id}/cancel
Cancel an automarking or exam-marker job and refund unused credits
Requires the `marking` scope.
/api/v1/interactive-feedback/jobs
Queue interactive feedback
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
student_text |
string | yes |
marking_criteria |
array | yes |
callback_url |
string | no |
curl -X POST https://feedbackflows.org/api/v1/interactive-feedback/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"student_text": "example",
"marking_criteria": [
"Clarity"
],
"callback_url": "https://example.com/webhooks/feedbackflows"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/interactive-feedback/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"student_text": "example",
"marking_criteria": [
"Clarity"
],
"callback_url": "https://example.com/webhooks/feedbackflows"
},
)
await fetch("https://feedbackflows.org/api/v1/interactive-feedback/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"student_text": "example",
"marking_criteria": [
"Clarity"
],
"callback_url": "https://example.com/webhooks/feedbackflows"
}),
});
/api/v1/interactive-feedback/jobs/{job_id}
Interactive-feedback job status and result
Requires the `marking` scope.
/api/v1/interactive-feedback/jobs/{job_id}/cancel
Cancel an interactive-feedback job and refund unused credits
Requires the `marking` scope.
/api/v1/jobs
List recent jobs for this account, filtered by the key's scopes
/api/v1/jobs/estimate-cost
Estimate the credit cost of an async job
| Body field | Type | Required |
|---|---|---|
job_type |
string | yes |
file_count |
integer | no |
student_count |
integer | no |
curl -X POST https://feedbackflows.org/api/v1/jobs/estimate-cost \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"job_type": "example",
"file_count": 1,
"student_count": 1
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/jobs/estimate-cost",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"job_type": "example",
"file_count": 1,
"student_count": 1
},
)
await fetch("https://feedbackflows.org/api/v1/jobs/estimate-cost", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"job_type": "example",
"file_count": 1,
"student_count": 1
}),
});
/api/v1/learner-packs/jobs
Queue a learner pack build
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
student_id |
integer | yes |
template_id |
integer | no |
selected_result_refs |
array | no |
generation_options |
object | no |
callback_url |
string | no |
curl -X POST https://feedbackflows.org/api/v1/learner-packs/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"student_id": 1,
"template_id": 1,
"selected_result_refs": [],
"generation_options": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/learner-packs/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"student_id": 1,
"template_id": 1,
"selected_result_refs": [],
"generation_options": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/learner-packs/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"student_id": 1,
"template_id": 1,
"selected_result_refs": [],
"generation_options": "example"
}),
});
/api/v1/learner-packs/jobs/{job_id}
Learner pack job status and rendered document
Requires the `marking` scope.
/api/v1/learner-packs/jobs/{job_id}/cancel
Cancel a learner-pack job and refund unused credits
Requires the `marking` scope.
/api/v1/media-marker/jobs
Queue video or audio marking
Requires the `media` scope.
| Body field | Type | Required |
|---|---|---|
criteria |
string | yes |
media_base64 |
string | yes |
filename |
string | no |
education_level |
string | no |
persona |
string | no |
presentation_type |
string | no |
callback_url |
string | no |
curl -X POST https://feedbackflows.org/api/v1/media-marker/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"criteria": "example",
"media_base64": "UEsDBBQAAAAA",
"filename": "example",
"education_level": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/media-marker/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"criteria": "example",
"media_base64": "UEsDBBQAAAAA",
"filename": "example",
"education_level": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/media-marker/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"criteria": "example",
"media_base64": "UEsDBBQAAAAA",
"filename": "example",
"education_level": "example"
}),
});
/api/v1/media-marker/jobs/{job_id}
Media marking job status and feedback
Requires the `media` scope.
/api/v1/media-marker/jobs/{job_id}/cancel
Cancel a media-marker job and refund unused credits
Requires the `media` scope.
/api/v1/reference-check/jobs
Queue the full reference-check web pipeline
Requires the `integrity` scope.
| Body field | Type | Required |
|---|---|---|
document_text |
string | yes |
style |
string | no |
enable_semantic_check |
boolean | no |
match_refs |
boolean | no |
callback_url |
string | no |
curl -X POST https://feedbackflows.org/api/v1/reference-check/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"document_text": "example",
"style": "example",
"enable_semantic_check": false,
"match_refs": false
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/reference-check/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"document_text": "example",
"style": "example",
"enable_semantic_check": false,
"match_refs": false
},
)
await fetch("https://feedbackflows.org/api/v1/reference-check/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"document_text": "example",
"style": "example",
"enable_semantic_check": false,
"match_refs": false
}),
});
/api/v1/reference-check/jobs/{job_id}
Reference-check job status and report
Requires the `integrity` scope.
/api/v1/reference-check/jobs/{job_id}/cancel
Cancel a reference-check job and refund unused credits
Requires the `integrity` scope.
/api/v1/rubric-marking/jobs
Queue rubric marking for a class ZIP
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
rubric_id |
integer | yes |
zip_base64 |
string | yes |
filename |
string | no |
marking_style |
string | no |
grading_system |
string | no |
callback_url |
string | no |
credit_check_only |
boolean | no |
curl -X POST https://feedbackflows.org/api/v1/rubric-marking/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"rubric_id": 1,
"zip_base64": "UEsDBBQAAAAA",
"filename": "example",
"marking_style": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/rubric-marking/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"rubric_id": 1,
"zip_base64": "UEsDBBQAAAAA",
"filename": "example",
"marking_style": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/rubric-marking/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"rubric_id": 1,
"zip_base64": "UEsDBBQAAAAA",
"filename": "example",
"marking_style": "example"
}),
});
/api/v1/rubric-marking/jobs/{job_id}
Rubric marking job status and results
Requires the `marking` scope.
/api/v1/rubric-marking/jobs/{job_id}/cancel
Cancel a rubric marking job and refund unused credits
Requires the `marking` scope.
/api/v1/smart-essay/jobs
Queue essay marking (preferred over the synchronous endpoint)
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
essay_text |
string | yes |
marking_criteria |
string | yes |
education_level |
string | no |
persona |
string | no |
callback_url |
string | no |
curl -X POST https://feedbackflows.org/api/v1/smart-essay/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"essay_text": "example",
"marking_criteria": "example",
"education_level": "example",
"persona": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/smart-essay/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"essay_text": "example",
"marking_criteria": "example",
"education_level": "example",
"persona": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/smart-essay/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"essay_text": "example",
"marking_criteria": "example",
"education_level": "example",
"persona": "example"
}),
});
/api/v1/smart-essay/jobs/{job_id}
Essay marking job status and feedback
Requires the `marking` scope.
/api/v1/smart-essay/jobs/{job_id}/cancel
Cancel a smart-essay job and refund unused credits
Requires the `marking` scope.
/api/v1/worksheets/jobs
Queue worksheet generation
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
student_id |
integer | yes |
weaknesses_list |
array | no |
format |
string | no |
level |
string | no |
num_questions |
integer | no |
callback_url |
string | no |
curl -X POST https://feedbackflows.org/api/v1/worksheets/jobs \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"student_id": 1,
"weaknesses_list": [
"Clarity"
],
"format": "example",
"level": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/worksheets/jobs",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"student_id": 1,
"weaknesses_list": [
"Clarity"
],
"format": "example",
"level": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/worksheets/jobs", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"student_id": 1,
"weaknesses_list": [
"Clarity"
],
"format": "example",
"level": "example"
}),
});
/api/v1/worksheets/jobs/{job_id}
Worksheet job status and result
Requires the `marking` scope.
/api/v1/worksheets/jobs/{job_id}/cancel
Cancel a worksheet job and refund unused credits
Requires the `marking` scope.
/api/v1/automarking/jobs/{job_id}/export.csv
Export automarking results as CSV
Requires the `marking` scope.
/api/v1/automarking/results/{result_id}/export.pdf
Export one automarking result as PDF
Requires the `marking` scope.
/api/v1/classes/{class_id}/export.csv
Export a class roster as CSV
Requires the `analytics` scope.
/api/v1/learner-packs/jobs/{job_id}/export.pdf
Export a learner pack as PDF
Requires the `marking` scope.
/api/v1/media-marker/jobs/{job_id}/export.pdf
Export a media-marker report
Requires the `media` scope.
/api/v1/reference-check/jobs/{job_id}/export.pdf
Export a reference-check report as PDF
Requires the `integrity` scope.
/api/v1/rubric-marking/jobs/{job_id}/export.csv
Export rubric batch results as CSV
Requires the `marking` scope.
/api/v1/rubric-marking/results/{result_id}/export.pdf
Export one rubric result as PDF
Requires the `marking` scope.
/api/v1/smart-essay/jobs/{job_id}/export.pdf
Export a smart-essay report as PDF
Requires the `marking` scope.
/api/v1/worksheets/jobs/{job_id}/export.pdf
Export a completed worksheet as PDF
Requires the `marking` scope.
/api/v1/classes
List classes
/api/v1/classes
Create a class
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
name |
string | yes |
subject |
string | no |
curl -X POST https://feedbackflows.org/api/v1/classes \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "example",
"subject": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/classes",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"name": "example",
"subject": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/classes", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "example",
"subject": "example"
}),
});
/api/v1/classes/{class_id}
Update a class
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
name |
string | no |
subject |
string | no |
concluded |
boolean | no |
curl -X PATCH https://feedbackflows.org/api/v1/classes/{class_id} \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "example",
"subject": "example",
"concluded": false
}'
import os, requests
requests.patch(
"https://feedbackflows.org/api/v1/classes/{class_id}",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"name": "example",
"subject": "example",
"concluded": false
},
)
await fetch("https://feedbackflows.org/api/v1/classes/{class_id}", {
method: "PATCH",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "example",
"subject": "example",
"concluded": false
}),
});
/api/v1/classes/{class_id}/assignments
List assignments for a class
/api/v1/classes/{class_id}/assignments/{assignment_id}/results
Per-student outcomes for one assignment
Requires the `analytics` scope.
/api/v1/classes/{class_id}/results
Bulk export marking outcomes for a class
Requires the `analytics` scope.
/api/v1/classes/{class_id}/students
Add or remove students from a class
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
add_student_ids |
array | no |
remove_student_ids |
array | no |
curl -X PATCH https://feedbackflows.org/api/v1/classes/{class_id}/students \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"add_student_ids": [],
"remove_student_ids": []
}'
import os, requests
requests.patch(
"https://feedbackflows.org/api/v1/classes/{class_id}/students",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"add_student_ids": [],
"remove_student_ids": []
},
)
await fetch("https://feedbackflows.org/api/v1/classes/{class_id}/students", {
method: "PATCH",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"add_student_ids": [],
"remove_student_ids": []
}),
});
/api/v1/question-templates
List question templates
Requires the `marking` scope.
/api/v1/rubrics
List rubrics
/api/v1/rubrics
Create a rubric
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
name |
string | yes |
criteria |
string | yes |
marking_guidance |
string | no |
pass_rate |
integer | no |
max_attempts |
integer | no |
curl -X POST https://feedbackflows.org/api/v1/rubrics \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "example",
"criteria": "example",
"marking_guidance": "example",
"pass_rate": 1
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/rubrics",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"name": "example",
"criteria": "example",
"marking_guidance": "example",
"pass_rate": 1
},
)
await fetch("https://feedbackflows.org/api/v1/rubrics", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "example",
"criteria": "example",
"marking_guidance": "example",
"pass_rate": 1
}),
});
/api/v1/rubrics/{rubric_id}
Get one rubric with its criteria
/api/v1/students
List students
/api/v1/students
Create a student
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
name |
string | yes |
uln |
string | no |
class_ids |
array | no |
curl -X POST https://feedbackflows.org/api/v1/students \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "example",
"uln": "example",
"class_ids": []
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/students",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"name": "example",
"uln": "example",
"class_ids": []
},
)
await fetch("https://feedbackflows.org/api/v1/students", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "example",
"uln": "example",
"class_ids": []
}),
});
/api/v1/students/{student_id}
Update a student
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
name |
string | no |
uln |
string | no |
class_ids |
array | no |
curl -X PATCH https://feedbackflows.org/api/v1/students/{student_id} \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "example",
"uln": "example",
"class_ids": []
}'
import os, requests
requests.patch(
"https://feedbackflows.org/api/v1/students/{student_id}",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"name": "example",
"uln": "example",
"class_ids": []
},
)
await fetch("https://feedbackflows.org/api/v1/students/{student_id}", {
method: "PATCH",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "example",
"uln": "example",
"class_ids": []
}),
});
/api/v1/students/{student_id}/ai-history
AI detection history for one student
/api/v1/students/{student_id}/submissions
Marking results and detector runs for one student
Requires the `analytics` scope.
/api/v1/students/bulk
Create up to 200 students in one call (JSON array, {students: []}, or CSV)
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
students |
array | no |
curl -X POST https://feedbackflows.org/api/v1/students/bulk \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"students": []
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/students/bulk",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"students": []
},
)
await fetch("https://feedbackflows.org/api/v1/students/bulk", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"students": []
}),
});
/api/v1/students:bulk
Create up to 200 students in one call (JSON array, {students: []}, or CSV)
Requires the `marking` scope.
| Body field | Type | Required |
|---|---|---|
students |
array | no |
curl -X POST https://feedbackflows.org/api/v1/students:bulk \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"students": []
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/students:bulk",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"students": []
},
)
await fetch("https://feedbackflows.org/api/v1/students:bulk", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"students": []
}),
});
/api/v1/classes/{class_id}/assignments/{assignment_id}/analyze
Cohort analysis for one assignment
Requires the `analytics` scope.
/api/v1/students/{student_id}/progress-report
Generate a progress report for one student
Requires the `analytics` scope.
| Body field | Type | Required |
|---|---|---|
start_date |
string | no |
end_date |
string | no |
curl -X POST https://feedbackflows.org/api/v1/students/{student_id}/progress-report \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"start_date": "example",
"end_date": "example"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/students/{student_id}/progress-report",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"start_date": "example",
"end_date": "example"
},
)
await fetch("https://feedbackflows.org/api/v1/students/{student_id}/progress-report", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"start_date": "example",
"end_date": "example"
}),
});
/api/v1/usage
Usage and credit consumption for this account's API keys
Requires the `analytics` scope.
/api/v1/webhooks/test
Send a signed ping webhook to verify your receiver
| Body field | Type | Required |
|---|---|---|
callback_url |
string | yes |
curl -X POST https://feedbackflows.org/api/v1/webhooks/test \
-H "X-API-Key: $FEEDBACKFLOWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"callback_url": "https://example.com/webhooks/feedbackflows"
}'
import os, requests
requests.post(
"https://feedbackflows.org/api/v1/webhooks/test",
headers={"X-API-Key": os.environ["FEEDBACKFLOWS_API_KEY"]},
json={
"callback_url": "https://example.com/webhooks/feedbackflows"
},
)
await fetch("https://feedbackflows.org/api/v1/webhooks/test", {
method: "POST",
headers: {
"X-API-Key": process.env.FEEDBACKFLOWS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"callback_url": "https://example.com/webhooks/feedbackflows"
}),
});
Job POSTs accept callback_url. Completions are signed with X-FeedbackFlows-Signature: t=<unix>,v1=<hex> over <timestamp>.<raw-body>. Also sent: X-FeedbackFlows-Delivery and X-FeedbackFlows-Timestamp. Reject timestamps older than five minutes. Use POST /webhooks/test to ping your receiver (5 per hour).
import hmac, hashlib, time
def valid(header, body: bytes, secret: str, now=None) -> bool:
parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p)
ts, sig = int(parts["t"]), parts["v1"]
if abs((now or time.time()) - ts) > 300:
return False
expected = hmac.new(secret.encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(sig, expected)
JSON bodies use error, code, status and request_id. Look for X-Request-Id on every response.
| Status | Code | Meaning |
|---|---|---|
| 400 | BAD_REQUEST | Malformed JSON or missing fields |
| 401 | UNAUTHORIZED / KEY_EXPIRED | Missing, invalid, or expired key |
| 402 | INSUFFICIENT_CREDITS | Not enough credits |
| 403 | SCOPE_FORBIDDEN | Key lacks the required scope |
| 404 | NOT_FOUND | Unknown resource |
| 429 | RATE_LIMITED | See Retry-After |
| 500 | INTERNAL_ERROR | Unexpected failure |