Batch Keywords — Generating & Sharing Registration Links with Schools
Audience: ops / program team setting up self-registration for a school. Scope: how a batch keyword is created (School → Batch → Batch onboarding), how it becomes a WhatsApp registration link, and how to share it with schools safely. Last updated: 2026-06-26 Companion docs: Student Onboarding — Operations Runbook §2 (the scratch path this feeds), Student Onboarding — System Architecture §2.
What a batch keyword is (and why it matters)
A batch keyword (e.g. GRSU47XQ) is the entry point for self-registration ("scratch" onboarding). A student taps a WhatsApp link that pre-fills tapschool:<keyword>, sends it, and the Glific registration flow starts — collecting their details and creating their Student record. The keyword is what tells TAP LMS which school and which batch the student is registering into.
One keyword = one Batch onboarding record = one (school, batch) pairing. Share the keyword's link with a school, and their students can self-register into that batch.
Step 1 — Create the School
In Desk: School → New.
name1is the school's display name. Its first two letters seed the keyword, so a sensible name matters (e.g. "Greenfield" →GR…).
Step 2 — Create the Batch
In Desk: Batch → New.
name1— batch display name (first two letters also seed the keyword, e.g. "Summer" →…SU…).batch_id— the batch identifier shown in the sheet.active— must be checked for registration to work and for the batch to appear in the sheet.start_date/end_date— the cohort window.regist_end_date— registration cutoff. Once this date passes, registration is rejected and the batch drops out of the sheet. Set it to when self-registration should close.
Step 3 — Create the Batch onboarding (this generates the keyword)
In Desk: Batch onboarding → New.
school— link to the Step-1 school.batch— link to the Step-2 batch.kit_less— set per the school's kit status (affects course-level resolution downstream).- Leave
batch_skeywordblank. On save, it is auto-generated.
The keyword is built as: <2 letters of school name1> + <2 letters of batch name1> + <2-digit number> + <2 random letters> — e.g. GRSU47XQ. It is collision-checked against existing keywords, so each is unique. (If you need a specific keyword, you can type one into batch_skeyword before saving and it will be kept — but auto-generated is the norm.)
The registration link
For a keyword GRSU47XQ, the WhatsApp registration link is:
https://api.whatsapp.com/send?phone=918454812392&text=tapschool:GRSU47XQ
When a student opens it, WhatsApp launches with the message tapschool:GRSU47XQ pre-filled to the TAP WhatsApp number. They send it, and the registration flow begins. This link is what you share with the school — it is safe to distribute widely (it contains no credentials).
Note the
tapschool:prefix and the keyword are case- and spelling-sensitive — always copy the link from the sheet rather than typing it by hand.
The auto-populating Google Sheet
A Google Sheet with a bound Apps Script fetches all currently active batches and lists, per batch: School Name, Batch Keyword, Batch ID, Registration Link. It refreshes when the sheet is opened.
It calls one endpoint (replace <tap-lms-host> with your TAP LMS base URL):
GET https://<tap-lms-host>/api/method/tap_lms.api.list_batch_keyword?api_key=<API_KEY>
list_batch_keyword returns a row only for batches where active is checked and regist_end_date is today or later. So the sheet is a live view of "what can students register into right now."
Apps Script — keep the key out of the source
Store the key in Script Properties (Project Settings → Script Properties → add API_KEY) instead of pasting it into the code. Then:
function refreshBatchKeywords() {
var apiKey = PropertiesService.getScriptProperties().getProperty('API_KEY');
var url = 'https://<tap-lms-host>/api/method/'
+ 'tap_lms.api.list_batch_keyword?api_key=' + encodeURIComponent(apiKey);
var resp = UrlFetchApp.fetch(url, { method: 'get', muteHttpExceptions: true });
if (resp.getResponseCode() !== 200) {
Logger.log('Error: ' + resp.getResponseCode() + ' - ' + resp.getContentText());
return;
}
var rows = JSON.parse(resp.getContentText()).message || [];
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.clear();
sheet.getRange(1, 1, 1, 4)
.setValues([['School Name', 'Batch Keyword', 'Batch ID', 'Registration Link']]);
var data = rows.map(function (r) {
return [r.School_name, r.batch_keyword, r.batch_id, r.Batch_regLink];
});
if (data.length) sheet.getRange(2, 1, data.length, 4).setValues(data);
sheet.autoResizeColumns(1, 4);
}
function onOpen() { refreshBatchKeywords(); }
This is functionally the same as the original script, with the key moved out of the source so a sheet viewer can't read it. Anyone with edit access to the script can still see Script Properties — so still don't share the script-bearing sheet externally.
What to actually send a school
Send the school only:
- Their batch keyword (e.g.
GRSU47XQ). - Their registration link (the
api.whatsapp.com/send?...URL). - A one-line instruction: "Students tap this link, send the pre-filled message, and follow the prompts to register."
Do not send the Sheet, the Apps Script, or the API key.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| A batch isn't in the sheet | active unchecked, or regist_end_date has passed |
Re-check active / extend regist_end_date on the Batch |
| Sheet shows an error / no rows | Bad or rotated API key | Confirm the key in Script Properties matches an enabled API Key record |
| Student gets "Invalid batch_skeyword" on registration | Link has a stale/mistyped keyword | Re-copy the link from the sheet; confirm the Batch onboarding still exists |
| Student gets "The batch is not active" / "Registration … has ended" | Batch closed | Re-activate the batch or extend regist_end_date (see the onboarding runbook §2.4) |
| Two batches collided on a keyword | Shouldn't happen — keywords are uniqueness-checked on save | If you hand-set batch_skeyword, ensure it's unique |
Pointers
- The scratch self-registration path this feeds: Student Onboarding — Operations Runbook §2 and System Architecture §2.
- Endpoint behaviour:
tap_lms.api.list_batch_keyword(active-batch filter),verify_batch_keyword,get_batch_keywords_by_phone.