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.

bash
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/enrollmentspriceMinor/currency set what this student is charged for this group (a fee schedule can compute this for you; see Billing).

bash
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.

bash
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.

bash
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):

bash
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.