Getting started
The eLearning.edu.pl Integration API lets your HR system, identity provider or reporting tool exchange people, course assignments and compliance status with the platform.
1. Get credentials
Ask the IT administrator of your organisation to create an integration client in the IT administration panel. The administrator chooses:
- scopes — what the client may do (
users:read,users:write,enrollments:write,compliance:read,webhooks:manage,scim); - authentication methods — API key, OAuth 2.0 client credentials, or both;
- optionally an IP allowlist and an expiry date.
You receive a client id and a secret of the form lms_live_<12 characters>_<32 characters>. The secret is shown once;
store it in a secrets manager.
You also need your tenant code — the identifier of your organisation, shown in the IT administration panel.
2. Make the first request
BASE_URL="${BASE_URL:-https://api.elearning.edu.pl}"
curl --fail-with-body -sS "$BASE_URL/api/v1/users?limit=5" \
-H "X-Tenant-Code: $TENANT_CODE" \
-H "X-API-Key: $API_KEY"import os
import requests
BASE_URL = os.environ.get("BASE_URL", "https://api.elearning.edu.pl")
response = requests.get(
f"{BASE_URL}/api/v1/users",
headers={
"X-Tenant-Code": os.environ["TENANT_CODE"],
"X-API-Key": os.environ["API_KEY"],
},
params={"limit": 5},
timeout=30,
)
response.raise_for_status()
for user in response.json()["users"]:
print(user["employee_no"], user["first_name"], user["last_name"])<?php
require __DIR__ . '/vendor/autoload.php';
$client = new GuzzleHttp\Client([
'base_uri' => getenv('BASE_URL') ?: 'https://api.elearning.edu.pl',
'timeout' => 30,
]);
$response = $client->request('GET', '/api/v1/users', [
'headers' => [
'X-Tenant-Code' => getenv('TENANT_CODE'),
'X-API-Key' => getenv('API_KEY'),
],
'query' => ['limit' => 5],
]);
$page = json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR);
foreach ($page['users'] as $user) {
echo $user['employee_no'], ' ', $user['first_name'], ' ', $user['last_name'], PHP_EOL;
}package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type user struct {
EmployeeNo string `json:"employee_no"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
func main() {
baseURL := os.Getenv("BASE_URL")
if baseURL == "" {
baseURL = "https://api.elearning.edu.pl"
}
req, err := http.NewRequest("GET", baseURL+"/api/v1/users?limit=5", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-Tenant-Code", os.Getenv("TENANT_CODE"))
req.Header.Set("X-API-Key", os.Getenv("API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
fmt.Fprintln(os.Stderr, "request failed:", res.Status)
os.Exit(1)
}
var page struct {
Users []user `json:"users"`
}
if err := json.NewDecoder(res.Body).Decode(&page); err != nil {
panic(err)
}
for _, u := range page.Users {
fmt.Println(u.EmployeeNo, u.FirstName, u.LastName)
}
}const BASE_URL = process.env.BASE_URL ?? "https://api.elearning.edu.pl";
const response = await fetch(`${BASE_URL}/api/v1/users?limit=5`, {
headers: {
"X-Tenant-Code": process.env.TENANT_CODE ?? "",
"X-API-Key": process.env.API_KEY ?? "",
},
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
const page = await response.json();
for (const user of page.users) {
console.log(user.employee_no, user.first_name, user.last_name);
}using System.Net.Http.Json;
using System.Text.Json;
var baseUrl = Environment.GetEnvironmentVariable("BASE_URL") ?? "https://api.elearning.edu.pl";
using var http = new HttpClient { BaseAddress = new Uri(baseUrl) };
http.DefaultRequestHeaders.Add("X-Tenant-Code", Environment.GetEnvironmentVariable("TENANT_CODE"));
http.DefaultRequestHeaders.Add("X-API-Key", Environment.GetEnvironmentVariable("API_KEY"));
using var response = await http.GetAsync("/api/v1/users?limit=5");
response.EnsureSuccessStatusCode();
var page = await response.Content.ReadFromJsonAsync<JsonElement>();
foreach (var user in page.GetProperty("users").EnumerateArray())
{
Console.WriteLine($"{user.GetProperty("employee_no")} {user.GetProperty("first_name")} {user.GetProperty("last_name")}");
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
String baseUrl = System.getenv().getOrDefault("BASE_URL", "https://api.elearning.edu.pl");
HttpRequest request = HttpRequest.newBuilder(URI.create(baseUrl + "/api/v1/users?limit=5"))
.header("X-Tenant-Code", System.getenv("TENANT_CODE"))
.header("X-API-Key", System.getenv("API_KEY"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IllegalStateException(response.statusCode() + " " + response.body());
}
// Parse the JSON with your library of choice (Jackson, Gson, …).
System.out.println(response.body());
}
}Every request needs the X-Tenant-Code header (SCIM: the tenant code is part of the path instead). The API host stays
the same even if your organisation is moved to another data-centre node, so you can hard-code it.
3. Next steps
- Authentication — API key vs. OAuth 2.0 tokens.
- Typical flow — synchronise people, assign courses, read compliance.
- Webhooks — get notified about completions and expirations instead of polling.
- Rate limits and errors — build a client that retries correctly.
Trying the API
Use a test organisation, separate from your production data — ask your onboarding contact for one. Create an integration client in its IT panel and call the API with its tenant code.