Massive Actions
Base URL: https://api-sls.platzi.com/production-sls-business-domains
Key Features:
- Upload a file directly to S3 via a presigned URL
- Start an asynchronous job and poll for progress
- Per-row error reporting with aggregate status
Workflow
POST /v1/massive-actions/{company_id}/presigned-upload-url/— get upload URLPUTthe file to the presigned URLPOST /v1/massive-actions/{company_id}/— start the job- Poll
GET /v1/massive-actions/{company_id}/{job_id}/until status is terminal
Job statuses: pending → processing → success | partial_success | error
Supported actions
| Action | Description |
|---|---|
invite_users | Invite (onboard) users in bulk, with optional per-user metadata |
assign_users_to_group | Add users (by email) to a group |
unassign_users_from_group | Remove users (by email) from a group |
deactivate_users | Deactivate users by email |
delete_users | Delete users by email |
resend_invitations | Resend pending invitations by email |
create_learning_paths | Create custom learning paths in bulk |
Invite users in bulk
Action: invite_users
Accepted file types: CSV (.csv)
File format: one row per user to invite.
| Column | Required | Description |
|---|---|---|
email | Yes | User email. Must be a valid address. |
name | No | User full name. |
licenses | No | Number of licenses to assign. Integer >= 0 (defaults to 0). |
| any other column | No | Treated as a metadata field. For companies with configured metadata fields, the column header must match one of them (by key or label). For companies without configured metadata fields, extra columns are accepted and ignored. |
The email, name, and licenses headers are reserved and matched case-insensitively. Every other column is interpreted as user metadata. Metadata is optional per row — a company configured for metadata can still upload rows that leave some (or all) metadata cells empty. If the company has no metadata fields configured, any extra columns in the file are silently ignored (no metadata is stored) and the rows are still invited.
Emails are case-insensitive. When the file contains two or more rows with the same email, only the first row is invited — the duplicates are ignored (no extra licenses are reserved and no duplicate invitation email is sent).
Use GET /v3/users/{company_id}/metadata-fields to discover which metadata fields a company accepts before building the file.
Request payload (optional):
{
"action": "invite_users",
"file_key": "<from presigned-upload-url>",
"payload": {
"metadata_columns": ["area", "sede"],
"skip_mail_send": false,
"skip_mail_validation": false
}
}
| Field | Default | Description |
|---|---|---|
metadata_columns | [] | Names of the metadata columns present in the uploaded file. Sent as a hint so the request can be rejected up front when a configured company doesn't accept one of them. Ignored when the company has no metadata fields configured. |
skip_mail_send | false | Skip sending the invitation email. |
skip_mail_validation | false | Skip email deliverability validation. |
Job-level validation (rejected with 400 before any row is processed):
| Error code | Meaning |
|---|---|
unknown_metadata_key | One or more declared metadata columns don't match any configured field (by key or label). Only applies to companies with metadata fields configured. |
Per-row result fields: email, error (on failure).
Common row errors:
| Error | Meaning |
|---|---|
missing_email | Row has no email value. |
invalid_email | Email is not a valid address. |
invalid_licenses | licenses is not an integer >= 0. |
invalid_metadata | A metadata value fails the company's field validation. |
invalid_row | The row could not be parsed. |
Create learning paths in bulk
Action: create_learning_paths
Accepted file types: CSV (.csv)
File format (wide): one row per learning path.
| Column | Required | Description |
|---|---|---|
ruta | Yes | Learning path title. Must be unique within the company catalog. |
curso_1 … curso_20 | At least one | Course IDs (integers) assigned to the path, in column order. Empty cells are ignored. |
Request payload (optional):
{
"action": "create_learning_paths",
"file_key": "<from presigned-upload-url>",
"payload": {
"step_title": "Programa",
"state": "active"
}
}
| Field | Default | Description |
|---|---|---|
step_title | Programa | Title of the single step that contains all courses |
state | active | Catalog state: draft, active, or archived |
Per-row result fields: ruta, learning_path_id (on success), error (on failure)
Common row errors:
| Error | Meaning |
|---|---|
missing_ruta | Row has no path title |
missing_course_ids | Row has no valid course IDs |
title_already_exists | A path with that title already exists |
courses_not_available | One or more course IDs are not in the company catalog |
Template file: see assets/templates/create_learning_paths_template.csv in the repository.
Example: start a bulk learning-path job
# 1. Presigned URL
POST /v1/massive-actions/123/presigned-upload-url/
{
"action": "create_learning_paths",
"filename": "rutas.csv",
"content_type": "text/csv"
}
# 2. PUT file to presigned_url
# 3. Start job
POST /v1/massive-actions/123/
{
"action": "create_learning_paths",
"file_key": "<file_key from step 1>",
"payload": { "step_title": "Programa" }
}
# 4. Poll
GET /v1/massive-actions/123/<job_id>/