Synchronize classes
Goal: create your academic system's disciplines and classes in Presente and keep the link between them. Unlike students and activities, there is no CSV import for classes: you use the create routes, one by one.
You need: CADASTRAR on the institution to create disciplines (role CURADOR) and CADASTRAR on the discipline to create classes (COORDENADOR of the discipline or CURADOR). See Permissions.
Keep the mapping
Presente has no external identifier field. To know which Presente class matches which class in your system, keep the relation on your side: class id in your system → class id in Presente (a UUID). When you create one, note the id in the response.
Two uniqueness rules change how careful you need to be:
| Resource | Uniqueness | If you repeat the creation |
|---|---|---|
| Discipline | unique sigla (code) and unique nome within the institution | 409 CONFLICT with fields: {"sigla": "taken"} (or nome). Safe. |
| Class | none | Creates another class with the same name. Do not repeat the creation: look it up first. |
Flow
- Find the institution (
GET /instituicoes, orusuario.vinculos[].instituicaoId). - Ensure the discipline (list; create if missing).
- Ensure the class (check your mapping; create only if missing).
- Set the period, if you have the dates.
- Deactivate finished classes, if needed.
1 and 2. Discipline
# does the discipline already exist? (search matches name and code)
curl "$API/instituicoes/$INST/disciplinas?busca=ENF101&limite=200" -H "Authorization: Bearer $TOKEN"
# create
curl -X POST "$API/instituicoes/$INST/disciplinas" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"sigla":"ENF101","nome":"Basic Nursing"}'sigla has up to 15 characters (letters, digits, ., _ and -; starts with a letter or digit); nome up to 200. ementa (text) and semanas (1 to 520) are optional. The discipline is born with the default assessment criteria.
Since sigla is unique, a simple and safe strategy is to create and handle 409: if CONFLICT comes with fields.sigla, the discipline already exists; read it from the listing.
3. Class
curl -X POST "$API/disciplinas/$DISC/turmas" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"nome":"Class A 2026/1"}'Only nome is required. Optional: endereco, localAtividade, lat, lng (used for the location fence of activities), toleranciaAntesMin and toleranciaDepoisMin (time window, 0 to 720 minutes) and notasVisiveisEm (date from which students see grades). The response is the created class, with the id you keep in your mapping.
Without the mapping (for example, on first use), look the class up by name before creating: GET /disciplinas/{disciplinaId}/turmas?busca=<name>.
4. Period
curl -X PUT "$API/turmas/$TURMA/periodo" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"dataInicio":"2026-03-02","dataFim":"2026-07-10"}'The period opens the deadline for the final feedback. Who can set it: the class teacher, the discipline coordinator and the institution curator (the integration account needs one of those roles). dataFim cannot be before dataInicio; send null in both to clear it.
5. Edit and deactivate
PATCH /turmas/{turmaId} changes the fields above and ativo:
curl -X PATCH "$API/turmas/$TURMA" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"ativo": false}'Deactivating does not delete: the class history stays available, and the class disappears from the default lists (use inativos=true to see it). GET /turmas/{turmaId}/prontidao returns only counts of what is already in place in the class (atividadesFuturas, alunos, alunosComAcesso, avaliadores, avaliadoresConvidados), useful to check the result of the synchronization.
Example (JavaScript): ensure the discipline and create the class once
async function call(method, path, body) {
const r = await fetch(`${API}${path}`, { method, headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" }, body: body && JSON.stringify(body) })
const data = r.status === 204 ? null : await r.json()
return { status: r.status, data }
}
// discipline: create; if the code already exists (409), look it up
let disc = await call("POST", `/instituicoes/${INST}/disciplinas`, { sigla: "ENF101", nome: "Basic Nursing" })
if (disc.status === 409) {
const list = await call("GET", `/instituicoes/${INST}/disciplinas?busca=ENF101&limite=200`)
disc = { data: list.data.items.find((d) => d.sigla === "ENF101") }
}
// class: only create if your mapping does not have it yet
let turmaId = myMapping.get("CLASS-A-2026-1")
if (!turmaId) {
const t = await call("POST", `/disciplinas/${disc.data.id}/turmas`, { nome: "Class A 2026/1" })
turmaId = t.data.id
myMapping.set("CLASS-A-2026-1", turmaId)
}What to do next
With the class created, bring in the students and the activities.