Install our app for a better experience!

API Endpoints & Payloads

API Reference

Base URL: https://<your-platform-host>/api/v1/

All requests authenticate with your per-organization API key, sent on every request:

X-API-Key: <your-raw-key>

(Authorization: Bearer <your-raw-key> is also accepted — the same org key.)

Endpoints

Method & path Purpose
GET /ping/ Test your key — returns your organization name.
GET /courses/ List the valid courses values (course-type names).
POST /provision/student/ Create + enrol a student.

GET /ping/

curl -s https://<host>/api/v1/ping/ -H "X-API-Key: <key>"
{ "status": "ok", "organization": "Acme Prep", "organization_slug": "acme-prep" }

GET /courses/

curl -s https://<host>/api/v1/courses/ -H "X-API-Key: <key>"
{ "status": "ok", "course_types": [ { "name": "ielts", "display_name": "IELTS" } ] }

POST /provision/student/

Request body (JSON):

Field Required Type Notes
email string The student's email — used as the unique identity.
first_name string
last_name string
courses string or array One or more course-type names (see table below). e.g. "ielts" or ["ielts","gmat"]. Omit it to add the user as a bare org member with no enrollment (e.g. someone who will only use custom tests).
tenure_months integer Access length, 1–120. Defaults to your org's configured default.
external_ref string Your reference (e.g. the WooCommerce order id). Stored for traceability.
send_welcome_email boolean Default true. Set false to email the student yourself.
source string Optional label ("pabbly", "zapier", …) recorded in the audit log.

Example:

{
  "email": "[email protected]",
  "first_name": "Jane",
  "last_name": "Doe",
  "courses": ["ielts", "gmat"],
  "tenure_months": 6,
  "external_ref": "wc_order_1234"
}

Success response (201 for a new account, 200 if the student already existed):

{
  "status": "success",
  "user_id": 4821,
  "created_user": true,
  "enrollments": [
    { "course_type": "ielts", "course_id": 12, "enrollment_id": 5567,
      "status": "active", "start_date": "2026-06-04", "end_date": "2026-12-04",
      "already_enrolled": false }
  ],
  "login_url": "https://<host>/login/",
  "set_password_url": "https://<host>/reset/MzQ/abc.../",
  "welcome_email_sent": true
}
  • status is already_provisioned if nothing new was created (a safe retry).
  • set_password_url is returned only for new accounts — you may email it yourself if you set send_welcome_email: false.

Error responses:

HTTP When Body
400 Bad payload (missing email/first_name/courses, unknown course type, bad tenure_months, invalid JSON) { "status": "error", "error": "<reason>" }
401 Missing/invalid/revoked API key { "status": "error", "error": "Invalid or missing API key…" }
403 The organization is not enabled for language tests { "status": "error", "error": "This organization is not enabled…" }
500 Unexpected server error — safe to retry { "status": "error", "error": "Internal error while provisioning. Safe to retry." }

Idempotency & retries

The endpoint is idempotent, so it's safe for automation tools that retry on failure:

  • Idempotency is keyed on the student's email. Calling again never creates a duplicate account; the repeat returns the same result with "already_enrolled": true.
  • A returning student whose access had lapsed (expired/dropped) is re-activated with fresh dates — not duplicated.
  • A suspended enrollment is never silently re-activated — provisioning leaves it as-is and returns it with "skipped_reason": "suspended". Lift the suspension in the admin to re-grant access.
  • Concurrent retries for the same student are safely serialized — no duplicate memberships or enrolments.
  • external_ref is stored for traceability/correlation; it is not the idempotency key.
  • A 500 is the only response you should retry. Never retry a 400 — fix the payload first (Pabbly/Zapier/Make treat 4xx as a permanent failure by default, which is correct here).

Course-type reference

Use these exact values in courses. (Call GET /courses/ for the live, org-specific list — only active types are provisionable.)

courses value Test
ielts IELTS (Academic)
ielts_general IELTS General Training
toefl TOEFL
pte_academic PTE Academic
pte_core PTE Core
oet OET
gre GRE
gmat GMAT
sat SAT
duolingo Duolingo English Test
celpip CELPIP
adaptive_language Adaptive Language Proficiency
custom Custom Language Test