Reports
Base URL: https://api.platzi.com/business
Reports endpoints expose read-only aggregated data about your company: user licenses and progress, learning paths, courses, exam skill analytics, and English placement test results. All endpoints require a valid company API key with the reports.read scope.
All responses follow the shared JSON envelope:
{
"data": [ ... ],
"metadata": { "count": 120, "page": 0, "page_size": 10 }
}
Pagination is 0-indexed (page=0 is the first page).
GET /v2/reports/users/ - Users Report
This endpoint retrieves detailed information about users, their progress, and their assigned learning paths within a company. It supports various query parameters to filter, search, and sort the data.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
company_id | number | yes | — | The unique identifier for the company. Filters the data to only include users of this company. |
page | number | no | 0 | Page index (0-based). |
page_size | number | no | 10 | Records per page. |
company_team_ids | string | no | — | Comma-separated team IDs. Only includes users belonging to the specified teams. |
learning_path_ids | string | no | — | Comma-separated learning path IDs. Only includes users assigned to those paths. |
state | string | no | — | Filter by user state. See allowed values below. |
user_ids | string | no | — | Comma-separated user IDs. Only includes the specified users. |
search | string | no | — | Case-insensitive search on name or email. |
order_by | string | no | — | Column to sort the results by. |
order_asc | boolean | no | false | Sort ascending when true; descending otherwise. Only applies when order_by is set. |
days_last_with_progress | number | no | — | Users who made progress within the last N days. |
days_last_without_progress | number | no | — | Users who did NOT make progress within the last N days. |
days_last_with_approved | number | no | — | Users who approved a course within the last N days. |
days_last_without_approved | number | no | — | Users who did NOT approve a course within the last N days. |
start_date | string | no | — | Lower bound for the date range filter (YYYY-MM-DD). |
end_date | string | no | — | Upper bound for the date range filter (YYYY-MM-DD). |
start_date_license | string | no | — | Include only users whose last active license started on/after this date (YYYY-MM-DD). |
end_date_license | string | no | — | Include only users whose last active license ended on/before this date (YYYY-MM-DD). |
start_date_first_license | string | no | — | Filter by start_date of the user's first-ever active license — lower bound (YYYY-MM-DD). |
end_date_first_license | string | no | — | Filter by start_date of the user's first-ever active license — upper bound (YYYY-MM-DD). |
Allowed state values:
active— user has access.processing— activation is being processed.matriculate— user has been invited; they must receive the email, click the link, and enter for the first time.inactive— still in the company, but with no access to the courses.error— some error occurred in any process.
Company metadata filters (optional)
If your company shares additional attributes for its users (the same metadata you provide when inviting or updating users), those attributes can be used to filter this report. Each shared attribute is available as a query parameter whose name matches the attribute you defined.
Filtering rules:
- Values are matched exactly but case-insensitively —
Norte,norte, andNORTEare equivalent. - Multiple comma-separated values for the same attribute act as OR.
- Different attributes combine as AND.
- Filtering by an attribute your company has not configured matches no users (the result set will be empty), rather than being silently ignored.
Users that match the filters also return those shared attributes as additional fields inside each user object.
# Attribute names depend on the metadata your company shares.
GET /v2/reports/users/?company_id=979&<attribute>=<value>&<other_attribute>=<valueA>,<valueB>
Example Request
GET /v2/reports/users/?company_id=979&page=0&page_size=10
x-platzi-company-api-key: platzi-xxxxxxxxxxxx.xxxxxxxx...
User-Agent: <your-user-agent>
Example Response
{
"data": [
{
"user_id": 14,
"company_id": 979,
"state": "active",
"name": "John Doe",
"email": "john.doe@email.com",
"avatar_url": "https://static.platzi.com/media/avatars/john_0e9aac7e-bd3f-412d-b626-4bf255ba0202.jpg",
"profile_url": "https://platzi.com/p/john/",
"start_date": "2020-04-06 00:00:00",
"end_date": "2030-02-10 00:00:00",
"start_date_license": "2024-01-01 00:00:00",
"end_date_license": "2025-01-01 00:00:00",
"first_activation_date": "2020-04-06 00:00:00",
"days_access": 1906,
"course_approved": 14,
"course_seen": 145,
"total_duration": 451,
"days_last_progress": 9,
"days_last_approved": 259,
"company_teams": [
{ "id": 1035, "team_name": "Team" },
{ "id": 20227, "team_name": "Inglés Avanzado C1" }
],
"lps": [
{
"learning_path_id": 16774,
"lp_name": "Mas servicios",
"progress_lp": 3,
"private": 1
},
{
"learning_path_id": 8036,
"lp_name": "Cursos obligatorios",
"progress_lp": 12,
"private": 0
}
]
}
],
"metadata": { "count": 1, "page": 0, "page_size": 10 }
}
Response Fields
Root fields
data: array of user objects.metadata: pagination details.
User object (inside data)
user_id: Unique identifier for the user.company_id: Identifier for the company the user belongs to.state: The user's current state (e.g.active).name: Full name of the user.email: Email address of the user.avatar_url: URL to the user's avatar image.profile_url: URL to the user's profile page.start_date: The date the user started their subscription or access.end_date: The date the user's subscription or access ends.start_date_license: The start date of the user's last active license.end_date_license: The end date of the user's last active license.first_activation_date: The start date of the first license. For traditional plans it is always-. If the user has not started yet, it is also-.days_access: Total number of days the user has access to the platform.course_approved: Number of courses the user has completed or approved.course_seen: Number of courses the user has viewed or started.total_duration: Total time in hours the user has spent on the platform.days_last_progress: Number of days since the user last made progress in a course.days_last_approved: Number of days since the user last completed or approved a course.
If your company shares additional user metadata, each shared attribute is returned here as an extra field on the user object (empty when the user has no value for it).
Nested fields
company_teams: teams the user is part of.id: Unique identifier for the team.team_name: Name of the team.
lps: learning paths assigned to the user.learning_path_id: Unique identifier for the learning path.lp_name: Name of the learning path.progress_lp: Progress percentage in the learning path.private:1= private (only users in the company),0= public (all Platzi users).
Metadata fields
count: Total number of user records available.page: Current page number in the paginated response (starts at0).page_size: Number of user records per page.
Key Notes
- The only required parameter is
company_id. - Other parameters are optional and allow for flexible filtering, searching, and sorting.
- Pagination is supported through
pageandpage_size. - Date-related filters (
start_date,end_date) and activity-based filters (days_last_with_progress,days_last_without_progress) help refine the results based on user activity.
GET /v2/reports/users/courses/ - User Courses Report
This endpoint retrieves basic information about users and a list of courses in which they have some progress. The progress can include courses that are started or already approved/certified. Each course includes specific details such as progress percentage, approval status, and title.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
company_id | number | yes | — | The unique identifier for the company. Filters the data to only include users of this company. |
page | number | no | 0 | Page index (0-based). |
page_size | number | no | 10 | Records per page. |
company_team_ids | string | no | — | Comma-separated team IDs. Only includes users belonging to the specified teams. |
learning_path_ids | string | no | — | Comma-separated learning path IDs. Only includes users assigned to those paths. |
state | string | no | — | Filter by user state. See allowed values below. |
user_ids | string | no | — | Comma-separated user IDs. Only includes the specified users. |
search | string | no | — | Case-insensitive search on name or email. |
order_by | string | no | — | Column to sort the results by. |
order_asc | boolean | no | false | Sort ascending when true; descending otherwise. Only applies when order_by is set. |
start_date | string | no | — | Lower bound for the date range filter (YYYY-MM-DD). |
end_date | string | no | — | Upper bound for the date range filter (YYYY-MM-DD). |
Allowed state values:
active— user has access.processing— activation is being processed.matriculate— user has been invited; they must receive the email, click the link, and enter for the first time.inactive— still in the company, but with no access to the courses.error— some error occurred in any process.
Company metadata filters (optional)
You can narrow this report to users that match the metadata your company shares (the same attributes you provide when inviting or updating users). Each shared attribute is available as a query parameter whose name matches the attribute you defined.
Filtering rules:
- Values are matched exactly but case-insensitively —
Norte,norte, andNORTEare equivalent. - Multiple comma-separated values for the same attribute act as OR.
- Different attributes combine as AND.
- Filtering by an attribute your company has not configured matches no users (the result set will be empty), rather than being silently ignored.
The shared attributes are used only to filter the users; they are not returned as fields in this endpoint's response.
Example Request
GET /v2/reports/users/courses/?company_id=979&page=0&page_size=10
x-platzi-company-api-key: platzi-xxxxxxxxxxxx.xxxxxxxx...
User-Agent: <your-user-agent>
Example Response
{
"data": [
{
"user_id": 14,
"name": "John Doe",
"email": "john.doe@email.com",
"courses": [
{
"course_id": 1111,
"progress_course": 40,
"total_progress_course": 76,
"duration_seen_seconds": 1820,
"total_duration_seen_seconds": 3480,
"approved_course": 0,
"in_progress_course": 1,
"course_title": "Curso Básico de Vue.js 2016",
"date_end_course": null,
"learning_path_id": 16774,
"learning_path_name": "Mas servicios",
"exam_attempts": {
"attempt_count": 2,
"attempts": [
{ "attempt_date": "2026-05-10", "score": 65, "approved": false, "strikes_used": 5 },
{ "attempt_date": "2026-05-12", "score": 88, "approved": true, "strikes_used": 2 }
]
}
},
{
"course_id": 1302,
"progress_course": 17,
"total_progress_course": 17,
"duration_seen_seconds": 600,
"total_duration_seen_seconds": 600,
"approved_course": 0,
"in_progress_course": 1,
"course_title": "Curso de Community Manager",
"date_end_course": null,
"learning_path_id": null,
"learning_path_name": null
}
]
}
],
"metadata": { "count": 1, "page": 0, "page_size": 10 }
}
Response Fields
Root fields
data: array of user objects, each representing a user and their associated courses.metadata: pagination details.
User object (inside data)
user_id: Unique identifier for the user.name: Full name of the user.email: Email address of the user.courses: array of courses in which the user has progress.
Course object (inside courses)
course_id: Unique identifier for the course.progress_course: Progress percentage in the course in the given date range (or historical if no date is present).total_progress_course: Historical progress percentage in the course.duration_seen_seconds: Duration in seconds seen in the given date range (or historical if no date is present).total_duration_seen_seconds: Historical duration in seconds seen in the course.approved_course: Indicates if the course is approved (1= approved,0= not approved).in_progress_course: Indicates if the course is currently in progress (1= in progress,0= not in progress).course_title: Title of the course.date_end_course: The date the course was completed or certified. If not completed, it isnull.learning_path_id: Learning path ID, if the course belongs to a learning path.learning_path_name: Learning path name, if the course belongs to a learning path.exam_attempts: Exam attempt details for the user in this course. Only present when the user has taken the course's exam at least once. It is omitted entirely when the course has no exam or the user has never taken it.attempt_count: Total number of exam attempts.attempts: array of attempts, each with:attempt_date: Date of the attempt (YYYY-MM-DD).score: Exam score (0–100).approved:trueif the attempt was approved,falseotherwise.strikes_used: Lives (strikes) consumed during the attempt (0–5). Each wrong answer consumes one life; at5the exam terminates as failed. Exams taken before the lives system existed always report0.
Metadata fields
count: Total number of user records available.page: Current page number in the paginated response (starts at0).page_size: Number of user records per page.
Key Notes
- The only required parameter is
company_id. - Other parameters are optional and allow for flexible filtering, searching, and sorting.
- Pagination is supported through
pageandpage_size.
Important
- Date range only captures the progress made within that window. If a user had 10% and two days later 30%, filtering those two days will return
20%(the delta). - The API is refreshed twice a day: 12:00 UTC and 18:00 UTC.
- Keep both refresh cadence and date range in mind:
- If you make a request at 19:00 UTC, you will only see data up to 18:00 UTC — plus the delta between the selected dates.
- The next day, the same request can return different progress if the user advanced after 18:00 UTC on the previous day.
GET /v2/reports/exams/skill-breakdown/ - Exam Skill Breakdown Report
This endpoint returns per-user exam attempts with a skill-level breakdown. Use it to identify which topics/skills a student struggled with on a specific exam attempt.
It complements exam_attempts in /v2/reports/users/courses/ (global score per attempt). This endpoint adds granular skill metrics for each terminal exam session.
Scope: Course exams only. Learning path exams are not included.
Data freshness: Reads directly from the core_exam_skill_attempts Tinybird datasource. When Education real-time ingestion is enabled, new attempts appear shortly after the student finishes. Historical data may require running the Django backfill script.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
company_id | number | yes | — | Company identifier. |
user_id_filter | number | no | — | Intentional filter to a single user (UI student filter). Auth-injected user_id from the gateway is ignored — use this param instead. |
skill_id_filter | string | no | — | Intentional filter to a single skill UUID. Server-side filter; metadata.count reflects the filtered total. |
course_id | number | no | — | Filter to a single course. |
session_id | string | no | — | Filter to a single exam session UUID. |
company_team_ids | string | no | — | Comma-separated team IDs. Only users belonging to those teams are included. |
page | number | no | 0 | Page number (0-indexed). |
page_size | number | no | 10 | Records per page. |
Example Request
GET /v2/reports/exams/skill-breakdown/?company_id=979&course_id=1302&user_id_filter=14&page=0&page_size=10
x-platzi-company-api-key: platzi-xxxxxxxxxxxx.xxxxxxxx...
User-Agent: <your-user-agent>
Example Response
{
"data": [
{
"user_id": 14,
"name": "John Doe",
"email": "john.doe@email.com",
"course_id": 1302,
"course_title": "Curso de Community Manager",
"session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"evaluation_id": "eval-uuid-here",
"attempt_date": "2026-06-20",
"overall_score": 65,
"approved": false,
"status": "completed",
"skill_results": [
{
"skill_id": "11111111-1111-1111-1111-111111111111",
"skill_name": "Redes sociales",
"questions_answered": 4,
"correct_count": 3,
"score_pct": 75.0,
"status": "strong"
},
{
"skill_id": "22222222-2222-2222-2222-222222222222",
"skill_name": "Copywriting",
"questions_answered": 3,
"correct_count": 1,
"score_pct": 33.3,
"status": "critical"
}
]
}
],
"metadata": { "count": 1, "page": 0, "page_size": 10 }
}
Response Fields
Root fields
data: Array of exam attempt rows (one per session).metadata: Pagination details.
Attempt object (inside data)
user_id: User identifier.name: User full name.email: User email.course_id: Course identifier.course_title: Course title.session_id: Exam session UUID (unique per attempt).evaluation_id: Evaluation UUID.attempt_date: Date of the attempt (YYYY-MM-DD).overall_score: Global exam score for this attempt (0–100), same scale asexam_attempts.score.approved:trueif the attempt was approved,falseotherwise (includes failed, expired, and abandoned attempts).status: Terminal session status —completed,expired, orabandoned.skill_results: Array of per-skill metrics for this attempt (see below).
Skill result object (inside skill_results)
skill_id: Skill UUID. Valueuncategorizedwhen the question's material has no skill mapping.skill_name: Skill display name at ingestion time.questions_answered: Number of exam questions counted toward this skill.correct_count: Number of correct answers for this skill.score_pct: Skill score percentage (0–100), calculated as(correct_count / questions_answered) * 100.status: Skill health indicator:critical—score_pct < 50needs_review—50 ≤ score_pct < 70strong—score_pct ≥ 70
Metadata fields
count: Total matching attempt records.page: Current page (0-indexed).page_size: Page size.
Key Notes
- The only required parameter is
company_id. - Use
user_id_filter(notuser_id) when scoping to a single student. The API gateway may injectuser_idfrom auth headers; that value is not used for data scoping. - Use
skill_id_filterto scope attempts to a single skill. Filtering is server-side —metadata.countis the full filtered total, not just the current page. - Filter by
user_id_filter+course_idto get all attempts for a student in a course. - Filter by
session_idto get the skill breakdown for one specific attempt. - A question linked to multiple skills increments each skill's counters.
- Failed attempts are included (
approved: false).
Relationship to /v2/reports/users/courses/
| Endpoint | What it shows |
|---|---|
/users/courses/ → exam_attempts | Global score + approved per attempt |
/exams/skill-breakdown/ | Same attempts, broken down by skill |
API Reference: Interactive schema and try-it-out docs are also available under Reports → Exam Skill Breakdown and Skill Performance.
GET /v2/reports/skills/performance/ - Skill Performance Report
This endpoint returns aggregated skill performance across company users for a course. Use it to answer “which skills is my team struggling with?”
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
company_id | number | yes | — | Company identifier. |
course_id | number | no | — | Filter to a single course. |
skill_id | string | no | — | Filter to a single skill UUID. |
threshold | number | no | 70 | Score % threshold for counting users as below target. |
company_team_ids | string | no | — | Comma-separated team IDs. |
page | number | no | 0 | Page number (0-indexed). |
page_size | number | no | 20 | Records per page. |
Example Request
GET /v2/reports/skills/performance/?company_id=979&course_id=1302&threshold=70&page=0&page_size=20
x-platzi-company-api-key: platzi-xxxxxxxxxxxx.xxxxxxxx...
User-Agent: <your-user-agent>
Example Response
{
"data": [
{
"course_id": 1302,
"course_title": "Curso de Community Manager",
"skill_id": "22222222-2222-2222-2222-222222222222",
"skill_name": "Copywriting",
"avg_score_pct": 48.5,
"users_tested": 12,
"users_below_threshold": 8,
"total_attempts": 15
},
{
"course_id": 1302,
"course_title": "Curso de Community Manager",
"skill_id": "11111111-1111-1111-1111-111111111111",
"skill_name": "Redes sociales",
"avg_score_pct": 72.3,
"users_tested": 12,
"users_below_threshold": 3,
"total_attempts": 15
}
],
"metadata": { "count": 2, "page": 0, "page_size": 20 }
}
Response Fields
Root fields
data: Array of aggregated skill rows (one per course + skill combination).metadata: Pagination details.
Skill performance object (inside data)
course_id: Course identifier.course_title: Course title.skill_id: Skill UUID.skill_name: Skill display name.avg_score_pct: Average skill score % across all attempts for this skill in this course.users_tested: Number of distinct users with at least one attempt row for this skill.users_below_threshold: Number of distinct users whose skill score % is below thethresholdparameter.total_attempts: Total(user, session, skill)rows aggregated (can exceedusers_testedwhen users retake exams).
Metadata fields
count: Total matching skill rows.page: Current page (0-indexed).page_size: Page size.
Key Notes
- Results are sorted by
avg_score_pctascending — weakest skills appear first. thresholddefaults to70(aligned with theneeds_review/strongboundary in skill-breakdown).thresholddoes not filter response rows; it only affectsusers_below_threshold.- Use
course_idto scope to a single course; omit it to aggregate across all courses with skill data for the company. users_below_thresholdis useful for prioritizing training interventions.
GET /v2/reports/users/classes-viewed/ - Classes Viewed Report
This endpoint retrieves a summary of classes viewed by users in the company.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
company_id | number | yes | — | The unique identifier for the company. Filters the data to only include users of this company. |
team_id | string | no | — | Team/group ID filter. Only includes users who belong to the specified team/group. |
state | string | no | — | Filter by user state. See allowed values below. |
start_date | string | no | — | Lower bound for the date range filter (YYYY-MM-DD). |
end_date | string | no | — | Upper bound for the date range filter (YYYY-MM-DD). |
Allowed state values:
active— user has access.processing— activation is being processed.matriculate— user has been invited; they must receive the email, click the link, and enter for the first time.inactive— still in the company, but no access.
Example Request
GET /v2/reports/users/classes-viewed/?company_id=979&start_date=2026-01-01&end_date=2026-01-31
x-platzi-company-api-key: platzi-xxxxxxxxxxxx.xxxxxxxx...
User-Agent: <your-user-agent>
Example Response
{
"data": [
{
"user_id": 1,
"company_user_id": 1,
"name": "John Doe",
"email": "john.doe@email.com",
"classes_viewed": 2
},
{
"user_id": 2,
"company_user_id": 2,
"name": "Jane Doe",
"email": "jane.doe@email.com",
"classes_viewed": 20
},
{
"user_id": 3,
"company_user_id": 3,
"name": "Jim Beam",
"email": "jim.beam@email.com",
"classes_viewed": 30
}
],
"metadata": {
"at_least_one_class_viewed": 3,
"three_or_more_classes_viewed": 2,
"count": 3,
"page": 1,
"page_size": 10
}
}
Response Fields
Root fields
data: paginated list of users with their classes-viewed totals.metadata: aggregate counters and pagination info for the filtered result set.
Object (inside data)
user_id: User identifier.company_user_id: Identifier of the user's membership in the company.name: User's full name.email: User's email address.classes_viewed: Number of classes the user has viewed within the filtered window.
Object (inside metadata)
at_least_one_class_viewed: Number of users who have seen at least one class.three_or_more_classes_viewed: Number of users who have seen 3 or more classes.count: Total number of users matching the filters.page: Current page index returned.page_size: Number of records per page.
Key Notes
- The only required parameter is
company_id. - Other parameters are optional and allow for flexible filtering.
Important
- The date range only counts progress within that window. If you send only
start_dateor onlyend_date, the filter is applied backwards or forwards from that date. - The API is refreshed twice a day: 12:00 UTC and 18:00 UTC.
- Keep both refresh cadence and date range in mind:
- If you make a request at 19:00 UTC, you will only see data up to 18:00 UTC — plus the delta between the selected dates.
- The next day, the same request can return different results if users advanced after 18:00 UTC on the previous day.
GET /v2/reports/learning-paths/ - Learning Paths Report
This endpoint retrieves a list of all learning paths for a specific company, including various metrics and details about each learning path. It also provides information about the teams to which the users with each learning path belong.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
company_id | number | yes | — | The unique identifier for the company. Filters the data to only include learning paths of this company. |
page | number | no | 0 | Page index (0-based). |
page_size | number | no | 10 | Records per page. |
company_team_ids | string | no | — | Comma-separated team IDs. Only includes learning paths with users on the specified teams. |
search | string | no | — | Case-insensitive search on the learning path name. |
order_by | string | no | — | Column to sort the results by. |
order_asc | boolean | no | false | Sort ascending when true; descending otherwise. Only applies when order_by is set. |
Example Request
GET /v2/reports/learning-paths/?company_id=979&page=0&page_size=10
x-platzi-company-api-key: platzi-xxxxxxxxxxxx.xxxxxxxx...
User-Agent: <your-user-agent>
Example Response
{
"data": [
{
"company_id": 979,
"learning_path_id": 15981,
"lp_name": "Tech Fundamentals",
"private": 1,
"lp_courses": 6,
"total_users": 11,
"progress_lp": 29,
"users_approved_lp": 0,
"users_in_progress_lp": 11,
"completed": 0,
"medium_completed": 2,
"company_teams": [
{ "id": 1035, "team_name": "Team" },
{ "id": 20227, "team_name": "Inglés Avanzado C1" }
]
}
],
"metadata": { "count": 11, "page": 0, "page_size": 10 }
}
Response Fields
Root fields
data: array of learning path objects, each representing a learning path and its associated metrics.metadata: pagination details.
Learning path object (inside data)
company_id: Unique identifier for the company.learning_path_id: Unique identifier for the learning path.lp_name: Name of the learning path.private:1= private (only users in the company),0= public (all users in the whole platform).lp_courses: Total number of courses included in the learning path.total_users: Total number of users assigned to the learning path.progress_lp: Average progress percentage across all users in the learning path.users_approved_lp: Number of users who have completed the learning path.users_in_progress_lp: Number of users currently in progress with the learning path.completed: Number of users who have completed the learning path (same asusers_approved_lp).medium_completed: Number of users with more than 50% of the learning path completed.company_teams: teams associated with the users in the learning path.id: Unique identifier for the team.team_name: Name of the team.
Metadata fields
count: Total number of learning paths available.page: Current page number in the paginated response (starts at0).page_size: Number of learning path records per page.
Key Notes
- The only required parameter is
company_id. - Other parameters are optional and allow for flexible filtering, searching, and sorting.
- Pagination is supported through
pageandpage_size. - This endpoint is useful for tracking learning path performance, user engagement, and team participation in an educational or corporate training platform.
GET /v2/reports/learning-paths/detail/ - Learning Path Detail
This endpoint retrieves detailed information about a specific learning path, including a list of users assigned to it, their progress metrics, and the courses that make up the learning path. Each course includes the progress of each user in that course.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
company_id | number | yes | — | The unique identifier for the company. Filters the data to only include learning paths of this company. |
learning_path_id | integer | yes | — | The unique identifier for the learning path to retrieve. |
page | number | no | 0 | Page index (0-based). |
page_size | number | no | 10 | Records per page. |
team_id | integer | no | — | Only includes users from the specified team. |
search | string | no | — | Case-insensitive search on user name or email. |
order_by | string | no | — | Column to sort the results by. |
order_asc | boolean | no | false | Sort ascending when true; descending otherwise. Only applies when order_by is set. |
progress_lp | integer | no | — | Filter users at a specific progress percentage in the learning path. |
user_ids | string | no | — | Comma-separated user IDs. Only includes the specified users. |
Example Request
GET /v2/reports/learning-paths/detail/?company_id=979&learning_path_id=15981&page=0&page_size=1
x-platzi-company-api-key: platzi-xxxxxxxxxxxx.xxxxxxxx...
User-Agent: <your-user-agent>
Example Response
{
"data": [
{
"lp_name": "Cursos obligatorios para el Team Platzi",
"private": 1,
"approved_by": "approved_by_exam",
"user_id": 5059834,
"name": "John Doe",
"email": "john.doe@email.com",
"avatar_url": "https://static.platzi.com/media/avatars/avatars/jhon-312e-418a-9426-4dd6003293f5.jpeg",
"profile_url": "https://platzi.com/p/john/",
"total_courses": 6,
"progress_lp": 100,
"approved_courses_lp": 6,
"assigned_at": "2023-09-18 10:30:00",
"date_init_lp": "2023-09-19 00:00:00",
"date_end_lp": "2024-09-10 00:00:00",
"company_teams": [{ "team_id": 1, "team_name": "Team 1" }],
"courses": [
{
"course_id": 1951,
"title_course": "Curso de Slack para Mejorar tu Comunicación Online",
"badge_course": "https://static.platzi.com/media/achievements/badges-comunicacion-slack-60710bd2-a4fd-49e6-86af-bb12ed8e7417.png",
"course_url": "https://platzi.com/cursos/slack/",
"progress_course": 100,
"approved_course": 1,
"date_init_course": "2023-09-19 00:00:00",
"date_end_course": "2023-09-20 00:00:00"
}
]
}
],
"metadata": { "count": 215, "page": 0, "page_size": 1 }
}
Response Fields
Root fields
data: array of user objects, each representing a user assigned to the learning path and their progress in the courses.metadata: pagination details.
Learning path user object (inside data)
lp_name: Name of the learning path.private:1= private (only users in the company),0= public (all users in the whole platform).approved_by: Method of approval for the learning path. Possible values:approved_by_exam,approved_by_placement,approved_by_courses,exam_pending.user_id: Unique identifier for the user.name: Full name of the user.email: Email address of the user.avatar_url: URL to the user's avatar image.profile_url: URL to the user's profile page.total_courses: Total number of courses in the learning path.progress_lp: Progress percentage of the user in the learning path.approved_courses_lp: Number of courses approved by the user in the learning path.assigned_at: The date the learning path was assigned to the user, or-when unavailable.date_init_lp: The date the user started the learning path.date_end_lp: The date the user completed the learning path, ornull.company_teams: teams associated with the user.team_id: Unique identifier for the team.team_name: Name of the team.
courses: per-course progress breakdown (see next section).
Course object (inside courses)
course_id: Unique identifier for the course.title_course: Title of the course.badge_course: URL to the badge or achievement image for the course.course_url: URL to the course page.progress_course: Progress percentage of the user in the course.approved_course:1= approved,0= not approved.date_init_course: The date the user started the course.date_end_course: The date the user completed the course.
Metadata fields
count: Total number of user records available.page: Current page number in the paginated response (starts at0).page_size: Number of user records per page.
Key Notes
- The required parameters are
company_idandlearning_path_id. - Other parameters are optional and allow for flexible filtering, searching, and sorting.
- Pagination is supported through
pageandpage_size. - This endpoint is useful for tracking user progress in a specific learning path, monitoring course completion, and generating detailed reports for educational or corporate training platforms.
GET /v2/reports/courses/ - Courses Report
This endpoint retrieves a list of courses that users in a specific company have completed or are currently working on. It includes metrics such as the number of users in progress, the number of users who have approved the course, and the total number of users assigned to each course. Additionally, it provides details about each course, such as its title, URL, and badge.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
company_id | number | yes | — | The unique identifier for the company. Filters the data to only include courses of this company. |
page | number | no | 0 | Page index (0-based). |
page_size | number | no | 10 | Records per page. |
company_team_ids | integer | no | — | Only includes courses associated with users from the specified teams. |
search | string | no | — | Case-insensitive search on the course title. |
order_by | string | no | — | Column to sort the results by. |
order_asc | boolean | no | false | Sort ascending when true; descending otherwise. Only applies when order_by is set. |
Example Request
GET /v2/reports/courses/?company_id=979&page=0&page_size=10
x-platzi-company-api-key: platzi-xxxxxxxxxxxx.xxxxxxxx...
User-Agent: <your-user-agent>
Example Response
{
"data": [
{
"users_in_progress": 6,
"users_approved": 160,
"total_users": 166,
"course_url": "https://platzi.com/cursos/platzi-business-model/",
"course_title": "NDA: Understanding Platzi's Business Model",
"course_badge": "https://static.platzi.com/media/achievements/understading_platzis_business_model-b9a327ff-a913-41bb-9dd8-bbbd13f2f924.png"
},
{
"users_in_progress": 6,
"users_approved": 143,
"total_users": 149,
"course_url": "https://platzi.com/cursos/slack/",
"course_title": "Curso de Slack para Mejorar tu Comunicación Online",
"course_badge": "https://static.platzi.com/media/achievements/badges-comunicacion-slack-60710bd2-a4fd-49e6-86af-bb12ed8e7417.png"
}
],
"metadata": { "count": 2079, "page": 0, "page_size": 10 }
}
Response Fields
Root fields
data: array of course objects, each representing a course and its associated metrics.metadata: pagination details.
Course object (inside data)
users_in_progress: Number of users currently in progress with the course.users_approved: Number of users who have completed or approved the course. Same value ascertified_student_count(canonical field).certified_student_count: Canonical count of certified students. Prefer this field in new integrations.total_users: Total number of users assigned to the course.course_url: URL to the course page.course_title: Title of the course.course_badge: URL to the badge or achievement image for the course.
Metadata fields
count: Total number of course records available.page: Current page number in the paginated response (starts at0).page_size: Number of course records per page.
Key Notes
- The only required parameter is
company_id. - Other parameters are optional and allow for flexible filtering, searching, and sorting.
- Pagination is supported through
pageandpage_size. - This endpoint is useful for tracking course engagement, user progress, and completion rates within a company, making it ideal for generating reports or dashboards for educational or corporate training platforms.
GET /v1/english/results/ - English Placement Results
English placement test results for users in the company, including attempts and associated learning paths.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
company_id | string | yes | Company ID |
email | string | no | Filter by a single user's email |
search | string | no | Search by user name or email |
page | string | no | Page number (default 0) |
page_size | string | no | Items per page (default 10) |
Example Request
GET /v1/english/results/?company_id=123&search=john&page=0&page_size=20
Response
{
"data": [
{
"user_id": 12345,
"name": "John Doe",
"email": "john@company.com",
"level": "B2",
"attempts": [
{ "date": "2026-02-10T12:30:00", "score": 74, "level": "B2" }
],
"learning_paths": [
{ "learning_path_id": 201, "title": "Business English" }
],
"company_teams": [{ "company_team_id": "10", "name": "Engineering" }]
}
],
"metadata": { "count": 40, "page": "0", "page_size": "20" }
}
GET /v2/reports/users/funnel/ - Student Funnel (Dashboard-aligned)
Returns the same funnel shown in the B2B reports dashboard: invited → with access → viewed class → taking courses → certified.
Each stage includes:
gt_30_days/lte_30_days— split used by the dashboard (>30 days vs ≤30 days in stage)no_access— users in stage without license accesstotal— sum ofgt_30_days + lte_30_days
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
company_id | number | yes | — | Company ID |
team_id | number | no | — | Filter by team |
period_type | string | no | rolling_30 | rolling_30, calendar_month, or calendar_quarter |
reference_date | string | no | today (UTC) | Reference date for calendar periods (YYYY-MM-DD) |
Example Request
GET /v2/reports/users/funnel/?company_id=979&period_type=calendar_month&reference_date=2026-06-01
x-platzi-company-api-key: platzi-xxxxxxxxxxxx.xxxxxxxx...
User-Agent: MyIntegration/1.0
Scope: reports.read
GET /v2/reports/users/inactive/ - Inactive Users (No Course Progress)
Users who have not made course progress in the last N days. Uses the same definition as the students report filter days_last_without_progress.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
company_id | number | yes | — | Company ID |
days | number | yes | — | No progress in the last N days |
team_id | number | no | — | Filter by team |
company_team_ids | string | no | — | Comma-separated team IDs |
page | number | no | 0 | Page index |
page_size | number | no | 10 | Page size |
search | string | no | — | Search by name or email |
Example Request
GET /v2/reports/users/inactive/?company_id=979&days=30&page=0&page_size=50
x-platzi-company-api-key: platzi-xxxxxxxxxxxx.xxxxxxxx...
User-Agent: MyIntegration/1.0
Scope: reports.read
GET /v2/reports/users/errors/summary/ - User Errors Summary
Count of users in error state grouped by error_code.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
company_id | number | yes | Company ID |
team_id | number | no | Filter by team |
Example Response
{
"data": [
{ "error_code": "6", "error_reason": "student has B2C paid subscription", "count": 12 },
{ "error_code": "7", "error_reason": "invalid email", "count": 3 }
],
"metadata": { "total_errors": 15, "company_id": 979 }
}
Scope: reports.read
GET /v2/reports/courses/top/approved/ - Top Certified Courses
Top courses ranked by number of certified students. Use certified_student_count as the canonical field (equals legacy course_approved).
| Parameter | Type | Required | Description |
|---|---|---|---|
company_id | number | yes | Company ID |
team_id | number | no | Team filter; omit for company-wide top |
Scope: reports.read
See also API Key Scopes for the full scope matrix.
Error Responses
Reports endpoints return a 400 for invalid query parameters:
{
"errors": [
{
"message": "company_id is required company_id",
"error_code": "invalid_string"
}
]
}