User Report Cards agregă metrici per-user (progres la cursuri, scoruri la survey-uri, activitate și altele) în view-uri de tip grid și detail, în panoul de administrare WordPress. Acest ghid este pentru dezvoltatorii externi care vor să citească aceleași date programatic — dintr-un serviciu de raportare, un sync către un data warehouse, un dashboard intern sau orice client HTTP din afara WordPress.
Tot ce urmează este servit de Enlivy Kit REST API, sub namespace-ul enlivy-kit/v1. Nu ai nevoie de cod de plugin de partea ta — doar de un client HTTP autentificat.
Toate endpoint-urile se află sub o singură cale de bază, versionată. Înlocuiește host-ul cu domeniul site-ului tău:
https://yourdomain.com/wp-json/enlivy-kit/v1/user-report-card
enlivy-kit/v1/user-report-cardContent-Type: application/json).Atenție — endpoint-urile de query folosesc
POST. Chiar dacă doar citesc date,/query/grid,/query/detailși/query/drilldownprimesc parametrii într-un corp JSON, deci sunt înregistrate caPOST. Este intenționat: selecțiile de card-uri și filtrele de useri sunt obiecte structurate care nu încap curat într-un query string. Tratează-le ca operațiuni de citire care se întâmplă să fie POST-uri.
Aceste rute sunt private — rezolvă date reale de useri, deci fiecare request trebuie autentificat ca un user WordPress care deține capability-ul potrivit. Există două moduri de autentificare:
X-WP-Nonce — doar când apelezi din JavaScript, într-o sesiune wp-admin logată. Pentru orice din afara browser-ului, folosește un Application Password.reporting_bot) și generează-l.curl https://yourdomain.com/wp-json/enlivy-kit/v1/user-report-card/config \
-u "reporting_bot:abcd EFGH ijkl MNOP qrst UVWX"
Valoarea de după două puncte este Application Password-ul generat (spațiile fac parte din el și sunt ignorate de WordPress). Apelează întotdeauna prin HTTPS, ca să nu trimiți credențialul necriptat.
| Capability | Permite |
|---|---|
enlivy_kit_report_card_view |
Citește config, listează și citește view-uri, rulează query-uri grid / detail / drilldown și export. |
enlivy_kit_report_card_management |
Tot ce e mai sus, plus crearea, actualizarea și ștergerea view-urilor salvate. |
Un user fără niciunul dintre capability-uri primește 401/403. Pentru o integrare read-only, un cont dedicat cu doar enlivy_kit_report_card_view este cea mai sigură alegere.
| Method | Path (după base URL) | Descriere | Capability |
|---|---|---|---|
| GET | /config |
Listează toate tipurile de card-uri înregistrate, grupurile și opțiunile lor de configurare. | view |
| GET | /views |
Listează view-urile salvate. | view |
| POST | /views |
Creează un view salvat. | manage |
| GET | /views/{view_id} |
Citește un singur view salvat. | view |
| PUT / PATCH | /views/{view_id} |
Actualizează un view salvat. | manage |
| DELETE | /views/{view_id} |
Șterge un view salvat. | manage |
| POST | /query/grid |
Rulează un query grid pentru mai mulți useri (endpoint-ul principal de citire). | view |
| POST | /query/detail |
Rulează un query detail pentru un singur user. | view |
| POST | /query/drilldown |
Drill-down în date ierarhice, pentru un user și un card. | view |
| GET | /views/{view_id}/export |
Export plat, pe rânduri/coloane, al unui view salvat (paginat cu cursor). | view |
Începe de aici. Endpoint-ul config îți spune ce tipuri de card-uri există pe acest site, cum sunt grupate și ce opțiuni de configurare acceptă fiecare. Folosești valorile type returnate pentru a construi request-urile de query.
GET /wp-json/enlivy-kit/v1/user-report-card/config
Response (prescurtat):
{
"data": {
"card_groups": {
"learning": { "label": "Learning", "order": 10 }
},
"cards": [
{
"type": "course_progress",
"label": "Course Progress",
"group": "learning",
"order": 10,
"supports_drilldown": true,
"config_options": [
{
"key": "date_range",
"type": "select",
"label": "Date Range",
"options": { "all_time": "All Time", "last_30": "Last 30 Days" },
"default": "all_time"
}
],
"display_formats": ["text", "percentage", "fraction"],
"default_display": "percentage"
}
]
}
}
type — identificatorul pe care îl treci în cards[].type dintr-un query.config_options — cheile pe care le poți seta sub cards[].config.supports_drilldown — dacă /query/drilldown are sens pentru acest card.Acesta este endpoint-ul pe care îl vei folosi cel mai des. Returnează un rând per user, cu o coloană per card cerut. Poți fie să îl indici către un view salvat (prin view_id), fie să furnizezi ad-hoc un set de cards și un user_filter inline.
POST /wp-json/enlivy-kit/v1/user-report-card/query/grid
Content-Type: application/json
{
"cards": [
{ "type": "course_progress", "label": "Onboarding", "config": { "date_range": "last_30" } }
],
"user_filter": { "groups": [] },
"order_by": [],
"per_page": 50,
"cursor": null
}
| Parametru | Tip | Note |
|---|---|---|
view_id |
string | Opțional. Dacă e setat, cards / user_filter vin din view-ul salvat, iar valorile din corp sunt ignorate (cu excepția order_by). |
cards |
array | Obligatoriu când nu există view_id. Fiecare intrare: { type, label?, config? }. Cel puțin unul este necesar. |
user_filter |
object | Ce useri să fie incluși, ex. { "groups": [...] }. groups gol înseamnă toți userii. |
order_by |
array | Specificație de sortare opțională, corelată cu sortable_columns din response. |
per_page |
int | Implicit 50. |
cursor |
object / null | Trimite înapoi cursor-ul din response-ul anterior ca să iei pagina următoare. |
{
"users": [
{
"user": { "id": 42, "email": "[email protected]", "display_name": "Jane Doe" },
"columns": {
"0": {
"value": 80,
"display_value": "80%",
"action_items": [ { "label": "Lessons", "completed": 8, "total": 10 } ],
"metadata": [ { "label": "Last Activity", "value": "2 days ago" } ]
}
}
}
],
"columns": {
"0": { "type": "course_progress", "label": "Onboarding", "display": "percentage" }
},
"total": 137,
"per_page": 50,
"has_more": true,
"cursor": { "after_user_id": 42 },
"sortable_columns": { }
}
users[].columns este indexat după poziția card-ului din request-ul tău ("0", "1", …), corespunzând cu columns.total este numărul complet de useri care se potrivesc; users conține doar pagina curentă.has_more este true, trimite cursor înapoi identic la apelul următor.Acolo unde grid-ul îți dă un rând de sumar, /query/detail returnează defalcarea completă pentru un singur user, pe toate card-urile cerute — sumarul plus payload-ul detail al fiecărui card.
POST /wp-json/enlivy-kit/v1/user-report-card/query/detail
Content-Type: application/json
{
"user_id": 42,
"cards": [ { "type": "course_progress", "config": {} } ]
}
{
"user_id": 42,
"user": { "id": 42, "email": "[email protected]", "display_name": "Jane Doe" },
"cards": [
{
"type": "course_progress",
"label": "Course Progress",
"config": {},
"summary": { "value": 80, "display_value": "80%" },
"detail": { "items": [ ], "summary": { "total": 10, "completed": 8 } }
}
]
}
user_id este obligatoriu. Ca și la grid, poți trimite view_id în locul unui array cards inline.
Pentru card-urile care anunță supports_drilldown: true, acest endpoint intră într-o ierarhie — de exemplu, de la un curs în jos, până la un capitol anume. Trimite un obiect path care descrie unde să coboare.
POST /wp-json/enlivy-kit/v1/user-report-card/query/drilldown
Content-Type: application/json
{
"user_id": 42,
"card_type": "course_progress",
"config": { "course_id": 5 },
"path": { "chapter_id": 12 }
}
user_id și card_type sunt obligatorii; un card_type necunoscut returnează 400. Rezultatul este returnat sub cheia data.
Un view este o combinație salvată de card-uri, un filtru de useri și o ordonare, identificată printr-un view_id precum view_9f1c…. View-urile îți permit să configurezi un raport o singură dată în admin și apoi să îl citești după ID. Listarea și citirea view-urilor necesită doar capability-ul view; crearea, actualizarea sau ștergerea lor necesită capability-ul management.
GET /wp-json/enlivy-kit/v1/user-report-card/views
{
"data": [
{
"id": "view_9f1c8a2e",
"name": "Cohort A — Onboarding",
"cards_count": 3,
"created_at": "2026-07-01 09:14:00",
"updated_at": "2026-07-05 11:02:00",
"created_by": 1
}
]
}
Ia definiția completă a unui singur view (card-uri, filtru, ordonare) cu GET /views/{view_id}, apoi trimite acel view_id direct în /query/grid sau /query/detail.
Endpoint-ul de export aplatizează un view salvat în headers și rows — ideal pentru a împinge datele într-un spreadsheet, un CSV sau un data warehouse. Este paginat cu cursor, după user ID, pentru export-uri stabile: chiar dacă activitatea se schimbă în timpul export-ului, nu primești rânduri duplicate sau omise.
GET /wp-json/enlivy-kit/v1/user-report-card/views/view_9f1c8a2e/export?per_page=200
{
"data": {
"view_name": "Cohort A — Onboarding",
"headers": ["User ID", "Email", "Display Name", "First Name", "Last Name", "Onboarding"],
"rows": [
[42, "[email protected]", "Jane Doe", "Jane", "Doe", "80%"]
],
"pagination": { "total": 137, "per_page": 200, "has_more": true, "last_user_id": 42 }
}
}
per_page este limitat între 50 și 500 (implicit 200).headers este returnat doar pe prima pagină (când after_user_id lipsește).last_user_id din response-ul anterior ca after_user_id: ?per_page=200&after_user_id=42. Continuă cât timp has_more este true.Atât grid-ul, cât și export-ul folosesc paginare cu cursor, nu numere de pagină: citește cursor-ul (cursor pentru grid, last_user_id pentru export) din fiecare response și trimite-l înapoi la request-ul următor, până când has_more este false. Cursorii sunt stabili la scrieri concurente, ceea ce paginarea cu offset nu este.
Erorile urmează forma standard WordPress REST: un obiect JSON cu code, message și un data.status care corespunde status-ului HTTP.
| Status | Code | Când |
|---|---|---|
| 400 | no_cards |
Un query a fost trimis fără card-uri (și fără un view care să le furnizeze). |
| 400 | missing_user_id |
/query/detail sau /query/drilldown apelat fără user_id. |
| 400 | missing_card_type / invalid_card_type |
Drilldown apelat fără card_type, sau cu unul care nu este înregistrat. |
| 401 / 403 | rest_forbidden |
Credențiale lipsă/invalide, sau userul nu are capability-ul necesar. |
| 404 | view_not_found |
view_id-ul referit nu există. |
{
"code": "no_cards",
"message": "At least one card is required",
"data": { "status": 400 }
}
Un flux minim de citire: descoperă card-urile, apoi trage prima pagină a unui grid pentru toți userii.
# 1. Ce card-uri există?
curl -s https://yourdomain.com/wp-json/enlivy-kit/v1/user-report-card/config \
-u "reporting_bot:abcd EFGH ijkl MNOP qrst UVWX"
# 2. Trage grid-ul pentru un card, toți userii, prima pagină
curl -s -X POST https://yourdomain.com/wp-json/enlivy-kit/v1/user-report-card/query/grid \
-u "reporting_bot:abcd EFGH ijkl MNOP qrst UVWX" \
-H "Content-Type: application/json" \
-d '{
"cards": [ { "type": "course_progress", "config": {} } ],
"user_filter": { "groups": [] },
"per_page": 50
}'
De acolo, iterează pe cursor-ul returnat până când has_more este false, sau treci la un view salvat și endpoint-ul /export pentru extrageri mari, dintr-o singură dată.