Content-injection-only flow
Content-injection = a partner (or an internal pipeline) that only wants to
push content into Itera programmatically, without full instructor seats or a
UI. In v1 this is not a separate permission — it is a use-case of the
author role using the same itera-mcp create_* / instantiate_program
tools.
Pattern
Section titled “Pattern”- Provision an Itera account with
authoron the target tenant (ask your Itera admin). Store its refresh token in your pipeline’s secret store. - Mint a fresh access token at run time (Supabase password grant, or refresh
via the MCP’s
/auth/refreshproxy — see Getting started → token refresh). - Connect to
itera-mcpwith that token (or call the tools over raw HTTP — see the raw HTTP tab). - Idempotency is on you:
slugis unique per tenant, so a re-run ofcreate_programwith the same slug returns a conflict (23505). Either catch it, orlist_programsfirst and branch toupdate_programwhen the slug already exists.
Bulk-load from your source of truth
Section titled “Bulk-load from your source of truth”A typical injector maps rows from your CMS/spreadsheet to the graph:
for each course in source: program = create_program(tenant_id, slug=course.slug, title_i18n=course.title) for each section in course.sections: unit = create_unit(program.id, ordinal=section.i, title_i18n=section.title) for each class in section.classes: lesson = create_lesson(unit.id, ordinal=class.i, title_i18n=class.title) for each step in class.steps: create_activity(lesson.id, kind=step.kind, ordinal=step.i, spec=step.spec, rubric=step.rubric)Keep a stable mapping from your source ids → returned Itera ids so re-runs
update_* instead of duplicating.
Cloning a canonical template
Section titled “Cloning a canonical template”If every injected course derives from one master template, author the template
once and instantiate_program per target — one call copies the whole graph, then
update_* the copies with the per-course specifics.