Quickstart
Four calls, in order: create a student, enroll them in a teaching group, mark them present at a session, and issue an invoice for the enrollment. Every response id below feeds the next call — copy them as you go, or read the ids back off each response instead of hardcoding these placeholders.
Before you start
You'll need a branchId and a groupId that already exist in your tenant (GET /api/v1/branches, GET /api/v1/groups) and an API key with students.write, enrollments.write, attendance.mark, and invoices.write. See Authentication.
1. Create a student
POST /api/v1/students — only branchId, firstName, and lastName are required; studentNumber auto-allocates if omitted.
curl -X POST "https://api.yourdomain.com/api/v1/students" \
-H "Authorization: Bearer $INSTITFLOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"branchId": "0190a1b2-0000-7000-8000-000000000001",
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada.lovelace@example.com",
"phone": "+15551234567"
}'The response is the created student, id 0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b below.
2. Enroll them in a group
POST /api/v1/enrollments — priceMinor/currency set what this student is charged for this group (a fee schedule can compute this for you; see Billing).
curl -X POST "https://api.yourdomain.com/api/v1/enrollments" \
-H "Authorization: Bearer $INSTITFLOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"studentId": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
"groupId": "0190a1b2-0000-7000-8000-000000000002",
"priceMinor": 12000,
"currency": "ILS"
}'3. Mark attendance
Attendance is per-session, bulk-upserted: PUT /api/v1/sessions/:id/attendance with one entry per student on the roster. Re-sending the same session's attendance later updates it in place — it's idempotent by design, not just by the Idempotency-Key header.
curl -X PUT "https://api.yourdomain.com/api/v1/sessions/0190a1b2-0000-7000-8000-000000000003/attendance" \
-H "Authorization: Bearer $INSTITFLOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"entries": [
{
"studentId": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
"status": "present"
}
]
}'4. Issue an invoice
Invoices are created as drafts, then issued — issuing is a separate call because a draft can be edited (or discarded) freely, while an issued invoice is a real, numbered financial document. Totals are always recomputed server-side from lines; never send a total yourself.
curl -X POST "https://api.yourdomain.com/api/v1/invoices" \
-H "Authorization: Bearer $INSTITFLOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"branchId": "0190a1b2-0000-7000-8000-000000000001",
"studentId": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
"issueDate": "2026-03-02",
"dueDate": "2026-03-16",
"currency": "ILS",
"lines": [
{
"description": "March tuition — Algebra I",
"quantity": 1,
"unitMinor": 12000,
"enrollmentId": "0190a1b2-0000-7000-8000-000000000004"
}
]
}'Then issue it (draft id from the previous response):
curl -X POST "https://api.yourdomain.com/api/v1/invoices/0190a1b2-0000-7000-8000-000000000005/issue" \
-H "Authorization: Bearer $INSTITFLOW_API_KEY"That's the core loop. From here: subscribe to a webhook so your system hears about invoice.issued/payment.recorded without polling, or browse the full Billing reference for payments, statements, and fee schedules.