Skip to content
GurukulLiveDevelopers
Reference

Errors & conventions

Every response uses the same envelope, every error has a stable machine-readable code, and every POST can be retried safely.

Envelope

Success
{
  "data": [ { "id": "cm2…", "externalId": "student-1001", "fullName": "Aarav Patel", "role": "STUDENT" } ],
  "meta": { "nextCursor": "eyJ0Ijoi…", "hasMore": true }
}
Error
{
  "error": {
    "code": "insufficient_scope",
    "message": "This API key is missing the required scope(s): meetings:write.",
    "details": { "required": ["meetings:write"], "missing": ["meetings:write"] }
  },
  "requestId": "req_01JA7Z…"
}

Branch on error.code, not on the message (messages may be reworded). Include requestId when you contact support.

Error codes

HTTPCodeMeaning
400validation_failedThe body or query is invalid; details lists each problem.
401unauthenticatedNo credentials were sent.
401invalid_api_keyThe key is malformed or unknown.
401api_key_revoked / api_key_expiredThe key no longer works — create a new one.
401invalid_join_token / join_token_revokedA join token is wrong or was revoked.
401session_expired / session_revokedA meeting session can no longer be refreshed — mint a new join link.
402plan_limit_reachedThe plan does not include this feature or limit (API access, participants, storage …).
403forbiddenThe credentials are valid but not allowed to do this.
403insufficient_scopeThe API key lacks a scope; details.missing lists it.
403ip_not_allowedThe request came from outside the key’s IP allowlist.
403wildcard_scope_forbiddenOnly the organization owner can create * keys.
403user_deactivated / not_a_member / not_enrolled / not_invitedThe user may not join this meeting.
404not_foundThe resource does not exist in your organization.
409conflict / external_id_conflictA unique value (e.g. externalId, e-mail) is already used.
409idempotency_in_progressA request with the same Idempotency-Key is still running — retry shortly.
409too_many_api_keysThe organization reached its active API key limit.
410join_token_expired / join_token_usedMint a new join link.
409meeting_cancelledThe meeting was cancelled.
410meeting_endedThe meeting is over.
422idempotency_key_reusedThe Idempotency-Key was used with a different request.
429rate_limitedToo many requests — see Retry-After.
500internal_errorSomething failed on our side; safe to retry with the same Idempotency-Key.
503service_unavailableTemporarily unavailable (e.g. media service); retry with backoff.

New codes may be added; treat unknown codes by their HTTP status.

Pagination

List endpoints take limit (default 50, maximum 100) and cursor. Pass meta.nextCursor back as cursor until meta.hasMore is false. Cursors are opaque.

js
let cursor;
do {
  const qs = new URLSearchParams({ limit: '100', ...(cursor ? { cursor } : {}) });
  const { data, meta } = await gurukullive(`/public/users?${qs}`);
  data.forEach(syncUser);
  cursor = meta.hasMore ? meta.nextCursor : undefined;
} while (cursor);

Idempotency

Send Idempotency-Key: <unique string> on POST requests. For 24 hours, repeating the same request with the same key returns the original response (with Idempotent-Replayed: true) instead of acting twice. Reusing a key for a different request fails with idempotency_key_reused; a retry while the first request is still running gets idempotency_in_progress. Good keys come from your own ids, e.g. create-meeting-<your class id>-<date>.

Other conventions

  • JSON and camelCase everywhere; send Content-Type: application/json.
  • Timestamps are ISO-8601 in UTC (2026-10-14T09:30:00.000Z); timeZone fields are IANA names (Asia/Kolkata).
  • Your ids: users, classes, courses, batches and meetings accept an externalId unique per organization; most paths accept either the GurukulLive id or your externalId.
  • CSV: attendance endpoints return CSV with Accept: text/csv.
  • Versioning: everything here is /api/v1; see the changelog for the compatibility promise.