Imports
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
multipart/form-data- body
file*FileSuccessful Response
application/json- response
id*Idfilename*Filenamemime_type*Mime Typesize_bytes*Size Bytescurl -X POST 'https://example.com/imports/uploads' \ -F 'file=string'{ "id": "string", "filename": "string", "mime_type": "string", "size_bytes": 0}semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
upload_id*Upload Id1 <= length <= 64Successful Response
application/octet-streamcurl -X GET 'https://example.com/imports/uploads/string/content'E.g. reject every item with import.duplicate_assessment. Give at least one
filter; they combine (an item must match all given). Rejecting a course item also rejects the items
that belong to it (its meetings, assessments, categories, events and tasks), so leaving a course out
takes only its id. The assistant gets changed and the session's summary, without its items.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
session_id*Session IdImport id, from imports.session.create or imports.session.list
application/json- body
decision*DecisionDecision to apply
"accept""reject"types?array<>|Only items of these types
issue_codes?array<string>|Only items with one of these issues
item_ids?array<>|Only these items (items[].id of imports.session.get)
Successful Response
application/json- response
changed*Changedsession*curl -X POST 'https://example.com/imports/string/items:decide' \ -H 'Content-Type: application/json' \ -d '{ "decision": "accept"}'{ "changed": 0, "session": { "id": "string", "program_id": "string", "source_kind": "ics", "target": { "kind": "term_wizard", "term_id": "string", "course_id": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" }, "status": "extracting", "job_id": "string", "source_refs": [ { "upload_id": "string", "file_item_id": "string", "filename": "string", "lms_course_id": "string", "status": "pending", "error_code": "string", "warning_code": "string" } ], "source_meta": {}, "summary": { "counts": { "property1": 0, "property2": 0 }, "accepted": { "property1": 0, "property2": 0 }, "issues": { "property1": 0, "property2": 0 }, "weights": [ { "course_ref": "string", "total": 0, "existing": 0, "ok": true } ], "category_weights": [ { "item_id": "string", "expected": 0, "total": 0, "ok": true } ], "created": 0, "updated": 0, "failed": 0 }, "error_code": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "committed_at": "2019-08-24T14:15:22Z", "items": [ { "id": "string", "session_id": "string", "type": "course", "data": {}, "evidence": { "property1": { "upload_id": "string", "file_item_id": "string", "page": 0, "quote": "string" }, "property2": { "upload_id": "string", "file_item_id": "string", "page": 0, "quote": "string" } }, "confidence": { "property1": "high", "property2": "high" }, "decision": "accept", "issues": [ { "code": "string", "params": {} } ], "depends_on": [ "string" ], "result": { "created_id": "string", "updated_id": "string", "reused": false, "error_code": "string", "error_params": {}, "skipped_exceptions": [ { "date": "string", "code": "string" } ] }, "position": 0 } ], "next_cursor": "string" }}data is merged into the item (send null to clear a field); fields the item's
type does not have are refused. The item's issues are checked again afterwards. The assistant (and
an HTTP caller with only_touched) gets the session's summary with only the items this change
touched: the edited one and those whose decision or issues changed with it.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
session_id*Session IdImport id, from imports.session.create or imports.session.list
item_id*Item IdItem id (items[].id of imports.session.get)
application/json- body
data?|Fields to change; merged into the item's data
decision?|accept, reject or pending
type?|Turn an assessment item into a task or back
only_touched?Only TouchedReturn only the items this change touched instead of all of them
falseSuccessful Response
application/json- response
id*Idprogram_id*Program Idsource_kind*Source Kind"ics""syllabus""timetable_image""lms""text""agent"target*status*Status"extracting""ready""committing""committed""failed""discarded"job_id*string|nullsource_refs*array<>source_meta*summary*error_code*string|nullcreated_at*Created Atdate-timeupdated_at*Updated Atdate-timecommitted_at*|nullitems*array<>next_cursor?|More items: pass it as cursor to imports.session.get
curl -X PATCH 'https://example.com/imports/string/items/string' \ -H 'Content-Type: application/json' \ -d '{}'{ "id": "string", "program_id": "string", "source_kind": "ics", "target": { "kind": "term_wizard", "term_id": "string", "course_id": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" }, "status": "extracting", "job_id": "string", "source_refs": [ { "upload_id": "string", "file_item_id": "string", "filename": "string", "lms_course_id": "string", "status": "pending", "error_code": "string", "warning_code": "string" } ], "source_meta": {}, "summary": { "counts": { "property1": 0, "property2": 0 }, "accepted": { "property1": 0, "property2": 0 }, "issues": { "property1": 0, "property2": 0 }, "weights": [ { "course_ref": "string", "total": 0, "existing": 0, "ok": true } ], "category_weights": [ { "item_id": "string", "expected": 0, "total": 0, "ok": true } ], "created": 0, "updated": 0, "failed": 0 }, "error_code": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "committed_at": "2019-08-24T14:15:22Z", "items": [ { "id": "string", "session_id": "string", "type": "course", "data": {}, "evidence": { "property1": { "upload_id": "string", "file_item_id": "string", "page": 0, "quote": "string" }, "property2": { "upload_id": "string", "file_item_id": "string", "page": 0, "quote": "string" } }, "confidence": { "property1": "high", "property2": "high" }, "decision": "accept", "issues": [ { "code": "string", "params": {} } ], "depends_on": [ "string" ], "result": { "created_id": "string", "updated_id": "string", "reused": false, "error_code": "string", "error_params": {}, "skipped_exceptions": [ { "date": "string", "code": "string" } ] }, "position": 0 } ], "next_cursor": "string"}The user reviews the import on its confirmation card; summarise it first.
Writes in dependency order; one item failing does not undo the others (see each item's
result). Repeating it only retries the items that have not been written. The assistant gets
the counts and the items that failed.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
session_id*Session IdImport id, from imports.session.create or imports.session.list
application/json- body
wizard_courses?array<>|Term wizard: the courses it created from the session's course items
item_ids?array<>|Retry only these items (failed ones, items[].id of imports.session.get); default: all accepted
Successful Response
application/json- response
session*created*Createdupdated*Updatedfailed*Failedcurl -X POST 'https://example.com/imports/string:commit' \ -H 'Content-Type: application/json' \ -d '{}'{ "session": { "id": "string", "program_id": "string", "source_kind": "ics", "target": { "kind": "term_wizard", "term_id": "string", "course_id": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" }, "status": "extracting", "job_id": "string", "source_refs": [ { "upload_id": "string", "file_item_id": "string", "filename": "string", "lms_course_id": "string", "status": "pending", "error_code": "string", "warning_code": "string" } ], "source_meta": {}, "summary": { "counts": { "property1": 0, "property2": 0 }, "accepted": { "property1": 0, "property2": 0 }, "issues": { "property1": 0, "property2": 0 }, "weights": [ { "course_ref": "string", "total": 0, "existing": 0, "ok": true } ], "category_weights": [ { "item_id": "string", "expected": 0, "total": 0, "ok": true } ], "created": 0, "updated": 0, "failed": 0 }, "error_code": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "committed_at": "2019-08-24T14:15:22Z", "items": [ { "id": "string", "session_id": "string", "type": "course", "data": {}, "evidence": { "property1": { "upload_id": "string", "file_item_id": "string", "page": 0, "quote": "string" }, "property2": { "upload_id": "string", "file_item_id": "string", "page": 0, "quote": "string" } }, "confidence": { "property1": "high", "property2": "high" }, "decision": "accept", "issues": [ { "code": "string", "params": {} } ], "depends_on": [ "string" ], "result": { "created_id": "string", "updated_id": "string", "reused": false, "error_code": "string", "error_params": {}, "skipped_exceptions": [ { "date": "string", "code": "string" } ] }, "position": 0 } ], "next_cursor": "string" }, "created": 0, "updated": 0, "failed": 0}Each import says where it came from and its state (extracting, ready, committed, failed, discarded). Open one with imports.session.get. Closed imports are kept for 30 days.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram id
cursor?|next_cursor of the previous page
limit?LimitPage size
50Successful Response
application/json- response
items*array<>next_cursor*string|nullcurl -X GET 'https://example.com/programs/string/imports'{ "items": [ { "id": "string", "program_id": "string", "source_kind": "ics", "target": { "kind": "term_wizard", "term_id": "string", "course_id": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" }, "status": "extracting", "job_id": "string", "source_refs": [ { "upload_id": "string", "file_item_id": "string", "filename": "string", "lms_course_id": "string", "status": "pending", "error_code": "string", "warning_code": "string" } ], "source_meta": {}, "summary": { "counts": { "property1": 0, "property2": 0 }, "accepted": { "property1": 0, "property2": 0 }, "issues": { "property1": 0, "property2": 0 }, "weights": [ { "course_ref": "string", "total": 0, "existing": 0, "ok": true } ], "category_weights": [ { "item_id": "string", "expected": 0, "total": 0, "ok": true } ], "created": 0, "updated": 0, "failed": 0 }, "error_code": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "committed_at": "2019-08-24T14:15:22Z" } ], "next_cursor": "string"}Use when the user shares a syllabus, timetable, ICS file or other document to
bring into the app ("import this", "set up my courses from this syllabus"). Creates a draft the user
reviews before anything is written. Pass the files themselves: attachment_ids for files attached
to the conversation, file_item_ids for course files (the app passes upload_ids), or text.
An import never creates terms: the target term must exist (academics.term.create first). ICS is
parsed at once (status ready); the other sources are extracted in the background (status
extracting → ready): call imports.session.get with wait_seconds to wait for it. Never write a
document's contents with the modules' own create capabilities instead of importing it. The
assistant gets summary and the first
25 items; read the rest with imports.session.get.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram id
application/json- body
source_kind*Source Kindics, syllabus, timetable_image, text, or agent for items you add yourself with imports.item.add_many
"ics""syllabus""timetable_image""lms""text""agent"target*A term or a course; agents cannot use the wizard
upload_ids?array<>Files uploaded in the app; agents use attachment_ids or file_item_ids
items <= 20file_item_ids?array<>Course files, from files.item.list
items <= 20attachment_ids?array<>Files the user attached to the assistant conversation (the id of an block); the importer reads the original file
items <= 10text?|Only for source_kind text: text the user pasted
source_meta?Extra source info, e.g. {provider, connection_id}; {only: 'course_info'} keeps just the field changes of the target course; {keep_files: false} does not save an uploaded syllabus to the course files
Successful Response
application/json- response
id*Idprogram_id*Program Idsource_kind*Source Kind"ics""syllabus""timetable_image""lms""text""agent"target*status*Status"extracting""ready""committing""committed""failed""discarded"job_id*string|nullsource_refs*array<>source_meta*summary*error_code*string|nullcreated_at*Created Atdate-timeupdated_at*Updated Atdate-timecommitted_at*|nullitems*array<>next_cursor?|More items: pass it as cursor to imports.session.get
curl -X POST 'https://example.com/programs/string/imports' \ -H 'Content-Type: application/json' \ -d '{ "source_kind": "ics", "target": { "kind": "term_wizard" }}'{ "id": "string", "program_id": "string", "source_kind": "ics", "target": { "kind": "term_wizard", "term_id": "string", "course_id": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" }, "status": "extracting", "job_id": "string", "source_refs": [ { "upload_id": "string", "file_item_id": "string", "filename": "string", "lms_course_id": "string", "status": "pending", "error_code": "string", "warning_code": "string" } ], "source_meta": {}, "summary": { "counts": { "property1": 0, "property2": 0 }, "accepted": { "property1": 0, "property2": 0 }, "issues": { "property1": 0, "property2": 0 }, "weights": [ { "course_ref": "string", "total": 0, "existing": 0, "ok": true } ], "category_weights": [ { "item_id": "string", "expected": 0, "total": 0, "ok": true } ], "created": 0, "updated": 0, "failed": 0 }, "error_code": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "committed_at": "2019-08-24T14:15:22Z", "items": [ { "id": "string", "session_id": "string", "type": "course", "data": {}, "evidence": { "property1": { "upload_id": "string", "file_item_id": "string", "page": 0, "quote": "string" }, "property2": { "upload_id": "string", "file_item_id": "string", "page": 0, "quote": "string" } }, "confidence": { "property1": "high", "property2": "high" }, "decision": "accept", "issues": [ { "code": "string", "params": {} } ], "depends_on": [ "string" ], "result": { "created_id": "string", "updated_id": "string", "reused": false, "error_code": "string", "error_params": {}, "skipped_exceptions": [ { "date": "string", "code": "string" } ] }, "position": 0 } ], "next_cursor": "string"}Use when the user does not want the import. Its uploaded files are deleted too.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
session_id*Session IdImport id, from imports.session.create or imports.session.list
Successful Response
application/json- response
id*Idprogram_id*Program Idsource_kind*Source Kind"ics""syllabus""timetable_image""lms""text""agent"target*status*Status"extracting""ready""committing""committed""failed""discarded"job_id*string|nullsource_refs*array<>source_meta*summary*error_code*string|nullcreated_at*Created Atdate-timeupdated_at*Updated Atdate-timecommitted_at*|nullcurl -X POST 'https://example.com/imports/string:discard'{ "id": "string", "program_id": "string", "source_kind": "ics", "target": { "kind": "term_wizard", "term_id": "string", "course_id": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" }, "status": "extracting", "job_id": "string", "source_refs": [ { "upload_id": "string", "file_item_id": "string", "filename": "string", "lms_course_id": "string", "status": "pending", "error_code": "string", "warning_code": "string" } ], "source_meta": {}, "summary": { "counts": { "property1": 0, "property2": 0 }, "accepted": { "property1": 0, "property2": 0 }, "issues": { "property1": 0, "property2": 0 }, "weights": [ { "course_ref": "string", "total": 0, "existing": 0, "ok": true } ], "category_weights": [ { "item_id": "string", "expected": 0, "total": 0, "ok": true } ], "created": 0, "updated": 0, "failed": 0 }, "error_code": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "committed_at": "2019-08-24T14:15:22Z"}Use to see what an import found (courses, assessments, meetings...) and what
needs checking (issues: unresolved dates, weights not adding up to 100, duplicates). summary
counts the items per type. Narrow it with item_ids (check one item after changing it), types and
fields; items come 25 at a time, follow next_cursor for more. While it is
extracting, pass wait_seconds (up to 25) to wait for the result in one call; if it
is still extracting after that, tell the user and stop instead of calling again.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
session_id*Session IdImport id, from imports.session.create or imports.session.list
item_ids?array<>|Only these items (items[].id of imports.session.get)
types?array<>|Only items of these types
fields?array<>|Agent/MCP only: return just these fields of each item (and its id); by default type, data, decision, issues and result
cursor?|next_cursor of the previous page
limit?|Items per page (agent/MCP default 25; HTTP: all)
wait_seconds?Wait SecondsWhile the import is still extracting, wait up to this long for it to finish before answering
0Successful Response
application/json- response
id*Idprogram_id*Program Idsource_kind*Source Kind"ics""syllabus""timetable_image""lms""text""agent"target*status*Status"extracting""ready""committing""committed""failed""discarded"job_id*string|nullsource_refs*array<>source_meta*summary*error_code*string|nullcreated_at*Created Atdate-timeupdated_at*Updated Atdate-timecommitted_at*|nullitems*array<>next_cursor?|More items: pass it as cursor to imports.session.get
curl -X GET 'https://example.com/imports/string'{ "id": "string", "program_id": "string", "source_kind": "ics", "target": { "kind": "term_wizard", "term_id": "string", "course_id": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" }, "status": "extracting", "job_id": "string", "source_refs": [ { "upload_id": "string", "file_item_id": "string", "filename": "string", "lms_course_id": "string", "status": "pending", "error_code": "string", "warning_code": "string" } ], "source_meta": {}, "summary": { "counts": { "property1": 0, "property2": 0 }, "accepted": { "property1": 0, "property2": 0 }, "issues": { "property1": 0, "property2": 0 }, "weights": [ { "course_ref": "string", "total": 0, "existing": 0, "ok": true } ], "category_weights": [ { "item_id": "string", "expected": 0, "total": 0, "ok": true } ], "created": 0, "updated": 0, "failed": 0 }, "error_code": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "committed_at": "2019-08-24T14:15:22Z", "items": [ { "id": "string", "session_id": "string", "type": "course", "data": {}, "evidence": { "property1": { "upload_id": "string", "file_item_id": "string", "page": 0, "quote": "string" }, "property2": { "upload_id": "string", "file_item_id": "string", "page": 0, "quote": "string" } }, "confidence": { "property1": "high", "property2": "high" }, "decision": "accept", "issues": [ { "code": "string", "params": {} } ], "depends_on": [ "string" ], "result": { "created_id": "string", "updated_id": "string", "reused": false, "error_code": "string", "error_params": {}, "skipped_exceptions": [ { "date": "string", "code": "string" } ] }, "position": 0 } ], "next_cursor": "string"}