Files and uploads
Upload a document, recording or course file once, then refer to it by file_id.
Three steps
POST /v1/fileswith the file name, type and exact size. The response has the file’sid, anupload_url, theupload_headersto send andupload_expires_at.PUTthe bytes toupload_urlwith every header inupload_headers, beforeupload_expires_at(about an hour). Whenupload_urlis the API’s own/v1/files/{id}/content, also send yourAuthorizationheader; never send it to any other upload URL.POST /v1/files/{id}/complete. EduMark checks the type and contents and scans for malware. Whenstatusisscanning, call again after a few seconds; use the file once it isready.
# Bash + jq. Upload essay.docx using every header the API returns.
SIZE=$(wc -c < essay.docx | tr -d ' ')
FILE_JSON=$(curl --fail-with-body -sS -X POST https://api.edumark.ai/v1/files \
-H "Authorization: Bearer $EDUMARK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d "{\"filename\":\"essay.docx\",\"mime_type\":\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\"size_bytes\":$SIZE}")
FILE_ID=$(printf '%s' "$FILE_JSON" | jq -r '.id')
UPLOAD_URL=$(printf '%s' "$FILE_JSON" | jq -r '.upload_url')
# Only the API's own content endpoint receives your API key.
upload_auth=()
if [ "$UPLOAD_URL" = "https://api.edumark.ai/v1/files/$FILE_ID/content" ]; then
upload_auth=(-H "Authorization: Bearer $EDUMARK_API_KEY")
fi
curl --fail-with-body -X PUT "$UPLOAD_URL" "${upload_auth[@]}" \
-H @<(printf '%s' "$FILE_JSON" | jq -r '.upload_headers | to_entries[] | "\(.key): \(.value)"') \
--data-binary @essay.docx
curl --fail-with-body -X POST https://api.edumark.ai/v1/files/$FILE_ID/complete \
-H "Authorization: Bearer $EDUMARK_API_KEY"Then send {"file_id": "file_…"} (the id from step 1) in any field that takes a document, such as document in marking or file in transcriptions and course imports. The file’s own expires_at is when EduMark deletes it: 30 days after upload, or sooner if you delete it.
Limits
| Kind | Limit |
|---|---|
| Documents (PDF, DOCX, TXT, CSV, XLSX, PPTX, PNG, JPEG, WebP) | 20 MiB, 50 pages |
| Audio and video (MP4, MOV, WebM, M4A, MP3, WAV, OGG) | 500 MiB, by file_id only |
| Course files for course imports (MBZ, IMSCC, ZIP, H5P, GIFT, XML) | 2 GiB, by file_id only |
| Inline base64 documents | Supported for small files; prefer file_id |
The upload URL can point to cloud storage for any file size. Send every returned upload header exactly, including Content-Length and x-amz-expected-bucket-owner when present. Recordings and course files are checked on a worker, so complete usually answers scanning: check again with GET /v1/files/{id} until the file is ready.
Fields that take a document also accept the older inline form {"filename", "base64", "mime_type"}. It is handy for tests, but uploads are faster and more reliable for anything larger than a few megabytes.
Course files
A course file is a course exported from another platform: a Moodle backup (.mbz), an IMS Common Cartridge or Canvas export (.imscc or .zip), a Blackboard export, a SCORM 1.2 or 2004, IMS content package, xAPI, cmi5 or H5P zip, or a GIFT, Aiken, QTI or Moodle XML question file. Send application/zip for zips and .imscc files, application/vnd.moodle.backup for .mbz and text/plain for .gift.
EduMark checks a course file the way its own course library does. It must be what its name says, not password protected, and a course export EduMark can read. A file that fails is rejected, and its error says what to do: SOURCE_ARCHIVE_ENCRYPTED (export it again without a password), SOURCE_ARCHIVE_UNSAFE (it unpacks too far: split it) or SOURCE_PACKAGE_UNRECOGNISED (not a course export). Then send it to course imports.