Skip to content

Synchronize activities ​

Goal: carry a class's calendar (lessons, shifts, practice sessions) from your system to Presente. There are two ways: CSV import (many activities at once, idempotent) and single create (one activity, with every field).

You need: CADASTRAR on the class (see Permissions) and the class id.

csv
data,inicio,fim,descricao,local
10/03/2026,08:00,12:00,Emergency room shift,Example Hospital
11/03/2026,14:00,16:00,Basic techniques lesson,Lab 2
ColumnRequiredFormat
datayesYYYY-MM-DD or DD/MM/YYYY (aliases: date, fecha).
inicio and fimno, but togetherHH:MM or HH:MM:SS; fim after inicio. Only one of the two filled in is an error.
descricaonoUp to 2000 characters.
localnoUp to 500 characters.

Limits and separators: the same as Synchronize students (500 lines, 90,000 characters, comma, semicolon or tab).

Usage is the same as the student import: POST /turmas/{turmaId}/importacoes/atividades with { "csv": "...", "modo": "simular" }, check the report and repeat with "modo": "aplicar" (all or nothing; parcial with hashConteudo as described there).

bash
curl -X POST "$API/turmas/$TURMA/importacoes/atividades" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile csv atividades.csv '{csv: $csv, modo: "aplicar"}')"

Idempotency: an activity is recognized by the combination date + start time + description (case-insensitive). Reapplying the same file gives JA_EXISTE for the ones that already exist and CRIADA for new ones. But:

  • The import only creates: it does not change or delete activities. If you change the time or description in your system, the import treats it as a new activity.
  • Two identical lines in the file: the second is ERRO (duplicate).
  • The descricao text becomes (or reuses, by name) an item of the discipline's activity catalog; always use the same spelling for the same activity. Fields the CSV does not have (mandatory, location fence, etc.) get default values; adjust them through the single create.

Single create ​

To control every field, or to change and cancel:

bash
curl -X POST "$API/turmas/$TURMA/atividades" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"data":"2026-03-10","horaInicio":"08:00","horaFim":"12:00","descricao":"Emergency room shift","local":"Example Hospital","obrigatoria":true}'

Only data is required. Other fields: atividadeProfissionalId (item of the discipline catalog), observacoes, obrigatoria, cancelada, cercaAtiva, cercaRaioM (10 to 5000 m), lat and lng. See the full model in AtividadeCriar.

Careful: POST /turmas/{turmaId}/atividades is not idempotent. If the call fails on the network after the server processed it, repeating it creates a duplicate activity. Before repeating after an uncertain failure, list the day's activities (GET /turmas/{turmaId}/atividades?de=2026-03-10&ate=2026-03-10) and check.

Read, change and remove ​

OperationRoute
List (with date filter de and ate)GET /turmas/{turmaId}/atividades
Read oneGET /turmas/{turmaId}/atividades/{atividadeId}
ChangePATCH /turmas/{turmaId}/atividades/{atividadeId}
Cancel (stays on the calendar)PATCH with {"cancelada": true}
RemoveDELETE /turmas/{turmaId}/atividades/{atividadeId}

Removing is only possible while the activity has no attendance recorded; after that the response is 409 CONFLICT. In that case, cancel instead of removing.

A calendar synchronization flow ​

  1. Read the class's current activities (all pages) and build a map date|start|description → id.
  2. For each activity in your system: if it is in the map, compare the fields and use PATCH if they changed; if it is not, create it (CSV or single).
  3. For activities your system removed that exist in Presente: cancel (PATCH with cancelada: true) or remove (DELETE, if it has no attendance).

This flow avoids the CSV limitation (it only creates) and duplicates nothing.

Example (Python): create the missing ones ​

python
def key(a):
    return (a["data"], (a["horaInicio"] or "")[:5], (a["descricao"] or "").lower())

existing = {key(a) for a in all_items(f"/turmas/{TURMA}/atividades", token)}  # see "Pagination and limits"

for a in my_system_calendar:
    if key(a) in existing:
        continue
    r = requests.post(f"{API}/turmas/{TURMA}/atividades",
                      headers={"Authorization": f"Bearer {token}"}, json=a)
    r.raise_for_status()

contato@presente.app.br