Facebook Pixel
Fit'DistanceDocumentation
Open the app
On this page

Remind students without a check-in for 14 days

Every Monday, send a short message to students who have sent no check-in for 14 days, with a first run that sends nothing.

Every Monday, students with no check-in for 14 days get a short message in the app. This use case writes in your name: it needs a key with Students › Read (students:read), Check-ins › Read (bilans:read) and Messages › Write (messaging:write), and an offer that includes writes. Create the key in the app, terms of use accepted.

What this use case does

  1. Trigger: every Monday, then GET /me for coach.first_name, the signature (free).
  2. Check-ins: GET /bilans?since=<14 days ago>, every page: the API calls them bilans. since applies to updated_at, which a comment also moves: so keep only the student_id of the check-ins whose submitted_at is greater than or equal to 14 days ago.
  3. Students: GET /students, every page. Each student missing from that set gets a message, unless the student joined less than 14 days ago or has a PAUSED or EXPIRED contract.
  4. Send: one POST /operations/messaging.send per student reminded.
curl -X POST https://api.fitdistance.io/api/partner/v1/operations/messaging.send \
  -H "Authorization: Bearer fd_live_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: bilan-42-2026-10-26" \
  -d '{"text": "Hi Léa, …", "studentId": 42}'

The Idempotency-Key is bilan-<id>-<YYYY-MM-DD>, with the date of the run: a replay the same day is refunded. See Writes and idempotency.

The message

Hi Léa, I haven't received a check-in from you in two weeks. When you have a moment, could you fill one in from the app? It helps me follow your progress.

Mathias

What it costs

A page read costs one credit, debited before the call; each message sent costs one. With 100 students and 40 recent check-ins: 3 pages read with limit=50, 2 with limit=200, then one message per student reminded. A refused parameter still costs a credit; a 401, a 403 or a 429 costs nothing; a replay is refunded.

A first run that sends nothing

messaging.send has no preview by studentId: dry_run: true gives a 400 DRY_RUN_UNSUPPORTED, free. So the first run lists the students without messaging them, for the price of the reads only.

In n8n

  1. Choose Import from URL… and paste https://fitdistance.io/documentation/api/cas-pratiques/eleve-sans-bilan-relance.n8n.json, or download the workflow and choose Import from File…. Pick the Fit'Distance API credential from Connect n8n in each HTTP Request node.
  2. Run it and read the output of Students to remind: one item per student, with its text.

Sending writes to real students

Send message ships disabled: enable it only after this first run. The Idempotency-Key prevents a duplicate the same day, not from one Monday to the next: a silent student is reminded every week, so trigger every other week to space them out.

  1. Enable Send message, run again, then activate the workflow. It sends at most one message per second.

The text is at the top of the code of Students to remind, in French: replace it with the English message above. The loop is the one of Connect n8n, plus a Code node, Collect check-ins, that keeps the ids of the pages read.

In Make

  1. First module HTTP › Make a request on GET /me; schedule on its clock: every Monday.
  2. HTTP › Make a request: GET on https://api.fitdistance.io/api/partner/v1/bilans, limit = 200, since = {{addDays(now; -14)}}. A filter on the link that follows: has_more equal to false, to stop rather than wrongly remind a student whose check-in is on the next page. Then an Iterator on data, a filter on submitted_at and a Flow Control › Array aggregator on student_id.
  3. HTTP › Make a request: GET on /students with limit = 200, an Iterator on data, then a filter: joined_at earlier than {{addDays(now; -14)}}, contract_status different from PAUSED and EXPIRED, and contains(map(<aggregated array>; student_id); id) false.
  4. Read the result of the filter, then add HTTP › Make a request: POST on /operations/messaging.send, Idempotency-Key = bilan-{{id}}-{{formatDate(now; YYYY-MM-DD)}}, Body content type application/JSON, Body input method JSON string, body {"text": "…", "studentId": {{id}}}.

The n8n workflow reads every page. Reference: students, check-ins, sending a message.

Next pageRemind inactive studentsEvery Monday, send a short message to students with no finished workout for 14 days, with a first run that sends nothing.