API Automation Guide¶
MOJO is an API-First Platform¶
The MOJO platform is designed from the ground up as an API-first automation platform. Every action you can perform in the MOJO web interface is also available through the REST API. This means you can fully automate your physical server lifecycle — from discovery and registration to pool management, firmware updates, and OS deployments — using any automation tool that can make HTTP requests.
Common automation platforms that integrate with MOJO include:
- VMware vRealize Orchestrator (vRO)
- Ansible / AWX / AAP
- ServiceNow
- Terraform
- Custom scripts (Python, Bash, PowerShell)
This guide walks through the most common API workflows for automating server lifecycle operations.
Interactive API Reference
Every MOJO instance includes built-in interactive API documentation:
- Swagger UI —
https://<your-mojo>/api/schema/swagger-ui/— Click the Authorize button to enter your API access token, then test any endpoint interactively right in the browser - ReDoc —
https://<your-mojo>/api/schema/redoc/— Best for reading detailed request/response schemas - OpenAPI Schema —
https://<your-mojo>/api/schema/— Raw schema for generating client libraries
These are always up-to-date with your installed MOJO version.
Getting Started¶
Authentication¶
All API requests require an API access token. Obtain one by sending your credentials to the token endpoint:
Token Lifetime
Tokens are valid for 24 hours by default. Use the refresh endpoint at /api/token/refresh/ to obtain a new access token without re-authenticating.
Once you have a token, include it in all subsequent requests:
PUT vs PATCH: Best Practices¶
MOJO supports both PUT and PATCH for updating resources. We strongly recommend using PATCH wherever possible:
| Method | Behavior | When to Use |
|---|---|---|
PUT |
Full replacement — you must send the complete object. Any field you omit may be reset to its default. | Only when you intend to replace the entire resource. |
PATCH |
Partial update — send only the fields you want to change. All other fields remain untouched. | Preferred for automation. Safer, less error-prone. |
Example — Update only a server's pool assignment:
Why PATCH is better for automation
When building automation workflows, PATCH prevents accidental data loss. If the MOJO API adds new fields in a future release, a PUT request that doesn't include them could reset those fields. PATCH only touches what you explicitly send.
Filtering, Searching & Pagination¶
MOJO's API includes powerful filtering, search, and sorting capabilities across all list endpoints. These are essential for working efficiently with large inventories.
Text Search¶
Use the search query parameter to perform a text search across multiple fields at once:
# Search servers by name, model, serial number, manufacturer, SKU, or BMC URL
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?search=PowerEdge"
# Search nodes by vendor, product, status, or URL
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/node/?search=dell"
# Search scan ranges by name, IP range, or status
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/node_discovery/scan_range/?search=Rack+1"
Search is case-insensitive and matches partial strings.
Field Filtering¶
Filter results by exact field values using query parameters that match field names:
# Servers in a specific pool
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?resource_pool=1"
# Servers with a specific power state
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?power_state=On"
# Firmware binaries filtered by type
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/firmware/?firmware_type=BIOS"
# OS images filtered by architecture
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/os/?arch=x86_64"
Discover available filters
The Swagger UI at ${MOJOHOST}/api/schema/swagger-ui/ shows all available filter fields for each endpoint. Look for the "Parameters" section on any list endpoint.
Sorting¶
Use the ordering query parameter to sort results. Prefix with - for descending order:
# Sort servers by name (ascending)
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?ordering=name"
# Sort servers by manufacturer (descending)
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?ordering=-manufacturer"
# Sort by pool name
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?ordering=resource_pool__name"
Common sortable fields for servers: name, model, serial_number, manufacturer, sku, bios_version, power_state, resource_pool__name
Combining Filters¶
You can combine search, filter, and ordering parameters in a single request:
# Dell servers in pool 1, sorted by name
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?search=Dell&resource_pool=1&ordering=name"
Pagination¶
List endpoints return all results by default. For large inventories, use pagination to retrieve results in manageable pages:
# Get the first 25 servers
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?page=1&page_size=25"
Paginated responses include navigation metadata:
{
"count": 150,
"next": "https://<your-mojo>/api/server/?page=2&page_size=25",
"previous": null,
"results": [ ... ]
}
| Parameter | Description |
|---|---|
page |
Page number (starting from 1) |
page_size |
Number of results per page (max 1000) |
count |
Total number of matching results |
next |
URL for the next page (null if on last page) |
previous |
URL for the previous page (null if on first page) |
Performance tip
For large deployments with hundreds of servers, always use pagination combined with filtering. Requesting all servers without pagination works but may be slower for very large inventories.
Server Discovery and Registration¶
The typical workflow for bringing new servers under MOJO management:
- Create a scan range — Define the IP range to search
- Run discovery — Scan the range for BMC/Redfish endpoints
- Check scan status — Wait for discovery to complete
- View discovered nodes — See what was found
- Register nodes — Authenticate and enroll nodes into MOJO
- Assign to a pool — Organize servers into resource pools
Step 1: Create a Scan Range¶
Define the network range where your server BMCs are located:
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{
"name": "Data Center Rack 1",
"ip_from": "10.0.1.1",
"ip_to": "10.0.1.50",
"ports": [443]
}' \
${MOJOHOST}/api/node_discovery/scan_range/
Note
Port 443 is the standard port for Redfish/BMC interfaces. Add additional ports if your environment uses non-standard configurations.
Step 2: Run Discovery¶
Start scanning across your configured scan ranges:
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"scan_ranges": [1]}' \
${MOJOHOST}/api/node_discovery/run_scan/
Replace 1 with the ID returned when you created the scan range.
Step 3: Check Scan Status¶
Poll the scan range to see if discovery is complete:
The status field will show "scanning" while in progress or "ready" when complete.
Step 4: View Discovered Nodes¶
List all discovered nodes:
Nodes with "status": "discovered" are ready to be registered.
Step 5: Register Nodes¶
Register a discovered node using an authentication profile that contains the BMC credentials:
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"auth_profile": 1}' \
${MOJOHOST}/api/node/42/register/
Replace 42 with the node ID and 1 with the authentication profile ID.
Authentication Profiles
Before registering nodes, you need an authentication profile with valid BMC credentials. See Managing Authentication Profiles below.
Step 6: Assign to a Pool¶
Once registered, add the server to a resource pool. See Resource Pool Management below.
Resource Pool Management¶
Resource pools organize your servers into logical groups with shared access controls. Pools support a hierarchy through sub-pools for fine-grained organization.
List All Pools¶
Each pool in the response includes:
| Field | Description |
|---|---|
id |
Pool identifier |
name |
Pool name |
description |
Pool description |
group |
The user group that controls access to this pool |
parent |
Parent pool ID (if this is a sub-pool) |
sub_pools |
List of child pools |
servers_count |
Number of servers in the pool |
switches_count |
Number of switches in the pool |
Get Pool Details¶
Retrieve full details for a pool, including all servers and switches:
Create a Pool¶
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{
"name": "Production Servers",
"description": "Production environment servers",
"group": 1
}' \
${MOJOHOST}/api/pool/
Group Assignment
The group field controls which users can see and manage the pool. Users can only access pools that belong to groups they are members of. Always assign a group to ensure proper access control.
Assign Servers to a Pool¶
Add one or more servers to a pool using their server IDs or node IDs:
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"servers": [1, 2, 3]}' \
${MOJOHOST}/api/pool/1/assign_servers/
Note
- Servers must not already be assigned to another pool. If a server is already in a pool, the response will indicate which pool it belongs to.
- You can pass either Server IDs or Node (BMC) IDs — MOJO will resolve both.
Alternative: You can also assign a single server by updating it directly:
curl -s -k -X PATCH \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"resource_pool": 1}' \
${MOJOHOST}/api/server/42/
Remove Servers from a Pool¶
Remove servers from their assigned pools (servers must not be in an active deployment):
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"servers": [1, 2]}' \
${MOJOHOST}/api/server/remove_from_pool/
Assign Switches to a Pool¶
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"switches": [1, 2]}' \
${MOJOHOST}/api/pool/1/assign_switches/
Create a Sub-Pool¶
Organize pools hierarchically by creating sub-pools:
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{
"name": "Linux Servers",
"description": "Linux production servers"
}' \
${MOJOHOST}/api/pool/1/create_sub_pool/
Update a Pool¶
curl -s -k -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{
"name": "Updated Pool Name",
"description": "New description",
"group": 1
}' \
${MOJOHOST}/api/pool/1/
Delete a Pool¶
Server Inventory¶
List All Servers¶
Retrieve all registered servers with hardware details, pool assignments, and BMC information:
You can filter, search, and sort results:
# Search by name, model, serial number, manufacturer, SKU, or BMC URL
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?search=PowerEdge"
# Filter by pool
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?resource_pool=1"
# Sort by name
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?ordering=name"
Get Server Details¶
Server Sub-Resources¶
Get detailed hardware information for a specific server:
# Processors
curl -s -k -H "Authorization: Bearer ${TOKEN}" \
${MOJOHOST}/api/server/42/processors/
# Ethernet interfaces
curl -s -k -H "Authorization: Bearer ${TOKEN}" \
${MOJOHOST}/api/server/42/ethernet_interfaces/
# Storage (controllers, drives, volumes)
curl -s -k -H "Authorization: Bearer ${TOKEN}" \
${MOJOHOST}/api/server/42/storages/
Firmware Inventory¶
List Firmware for a Server¶
Retrieve the full firmware inventory (BIOS, BMC, NIC firmware, storage controller firmware, etc.) for a specific server:
List Firmware Update Binaries¶
List all firmware update packages that have been uploaded to MOJO:
Get Firmware Binary Details¶
Managing Authentication Profiles¶
Authentication profiles store BMC credentials used when registering nodes. You can organize credentials by data center, rack, vendor, or any grouping that fits your environment.
List Profiles¶
Create a Profile¶
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{
"node_classification": "Dell Servers - DC1",
"bmc": "redfish"
}' \
${MOJOHOST}/api/node_discovery/auth_profile/
Add Credentials to a Profile¶
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{
"username": "admin",
"password": "your_bmc_password"
}' \
${MOJOHOST}/api/node_discovery/auth_profile/1/credentials/
You can add multiple credential pairs to a single profile. During registration, MOJO will try each credential until one succeeds.
List Credentials for a Profile¶
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
${MOJOHOST}/api/node_discovery/auth_profile/1/credentials/
Client Libraries & SDK Generation¶
MOJO publishes a full OpenAPI 3.0 schema at every installation, making it easy to generate client libraries in any language for your automation platform.
Downloading the OpenAPI Schema¶
# Download the schema in YAML format
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
${MOJOHOST}/api/schema/ -o mojo-openapi.yaml
# Or in JSON format
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/json" \
${MOJOHOST}/api/schema/ -o mojo-openapi.json
An OpenAPI Specification is also available outside of a MOJO installation for reference. You can browse and download the specifications.
Generating Client Libraries¶
Use OpenAPI Generator to create a typed client library in your preferred language:
vRealize Orchestrator (vRO)
For VMware vRO integrations, download the OpenAPI schema and import it as a REST endpoint in vRO. The schema provides all the type information vRO needs to generate typed workflow inputs and outputs.
Performance Tips¶
When automating against MOJO instances that manage hundreds or thousands of servers, these tips will help keep your integrations fast and efficient.
Request Only What You Need¶
- Use pagination for list endpoints:
?page=1&page_size=50instead of fetching all results at once - Use filters to narrow results at the server:
?resource_pool=1&power_state=Onis faster than fetching everything and filtering client-side - Use search for text lookups:
?search=PowerEdgelets the server do the work
Token Management¶
- Reuse tokens — API access tokens are valid for 24 hours. Cache and reuse them instead of requesting a new token for every API call
- Use token refresh — Call
/api/token/refresh/with your current token before it expires, rather than re-authenticating with username/password
# Refresh an existing token
curl -s -k -X POST \
-H "Content-Type: application/json" \
-d '{"refresh": "your_refresh_token"}' \
${MOJOHOST}/api/token/refresh/
Polling Best Practices¶
Some operations (discovery scans, firmware updates, OS deployments) are asynchronous. When polling for status:
- Start with longer intervals (5-10 seconds) and increase if the operation is still running
- Check the status field rather than re-fetching the full object list
- Use the specific resource URL (e.g.,
/api/node_discovery/scan_range/1/) instead of listing all scan ranges
Error Handling¶
MOJO uses standard HTTP status codes:
| Code | Meaning | Action |
|---|---|---|
200 |
Success | Process the response |
201 |
Created | Resource was created successfully |
202 |
Accepted | Async operation started — poll for status |
400 |
Bad Request | Check your request body for missing/invalid fields |
401 |
Unauthorized | Token expired or missing — re-authenticate |
403 |
Forbidden | User lacks permission — check pool/group assignments |
404 |
Not Found | Resource doesn't exist — check the ID and endpoint path |
429 |
Rate Limited | Slow down — add delays between requests |
500 |
Server Error | Internal error — check MOJO logs or contact support |
API Training: End-to-End Walkthrough¶
This section walks through a complete, real-world automation scenario from start to finish. Follow along with a live MOJO instance to practice.
Scenario: Discover, Register, and Organize New Servers¶
You've just racked 10 new Dell PowerEdge servers in Data Center Rack 5. Their BMCs are configured on the 10.50.5.0/24 network with default credentials. You need to discover them, register them in MOJO, and assign them to a "Production" resource pool.
1. Authenticate¶
export MOJOHOST="https://your-mojo-instance"
export TOKEN=$(curl -s -k -X POST \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "your_password"}' \
${MOJOHOST}/api/token/ | jq -r '.access')
# Verify authentication
curl -s -k -H "Authorization: Bearer ${TOKEN}" \
${MOJOHOST}/api/users/me/ | jq '.username'
2. Create an Authentication Profile for BMC Access¶
# Create the profile
PROFILE_ID=$(curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"node_classification": "Dell DC Rack 5", "bmc": "redfish"}' \
${MOJOHOST}/api/node_discovery/auth_profile/ | jq -r '.id')
echo "Created auth profile: ${PROFILE_ID}"
# Add BMC credentials
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"username": "root", "password": "bmc_password"}' \
${MOJOHOST}/api/node_discovery/auth_profile/${PROFILE_ID}/credentials/
3. Create a Scan Range and Discover¶
# Create scan range for the new rack
SCAN_ID=$(curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{
"name": "DC Rack 5",
"ip_from": "10.50.5.1",
"ip_to": "10.50.5.254",
"ports": [443]
}' \
${MOJOHOST}/api/node_discovery/scan_range/ | jq -r '.id')
echo "Created scan range: ${SCAN_ID}"
# Start discovery
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d "{\"scan_ranges\": [${SCAN_ID}]}" \
${MOJOHOST}/api/node_discovery/run_scan/
4. Wait for Discovery to Complete¶
# Poll scan status until complete
while true; do
STATUS=$(curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
${MOJOHOST}/api/node_discovery/scan_range/${SCAN_ID}/ | jq -r '.status')
echo "Scan status: ${STATUS}"
if [ "${STATUS}" != "scanning" ]; then
break
fi
sleep 10
done
5. Register Discovered Nodes¶
# List discovered (unregistered) nodes
NODES=$(curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/node/?status=discovered" | jq -r '.results[] | .id')
echo "Found nodes: ${NODES}"
# Register each node with our auth profile
for NODE_ID in ${NODES}; do
echo "Registering node ${NODE_ID}..."
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d "{\"auth_profile\": ${PROFILE_ID}}" \
${MOJOHOST}/api/node/${NODE_ID}/register/
done
6. Create a Pool and Assign Servers¶
# Create a resource pool
POOL_ID=$(curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{
"name": "Production - Rack 5",
"description": "Dell PowerEdge servers in DC Rack 5",
"group": 1
}' \
${MOJOHOST}/api/pool/ | jq -r '.id')
echo "Created pool: ${POOL_ID}"
# Get list of newly registered server IDs
SERVER_IDS=$(curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?search=PowerEdge&ordering=-id&page_size=10" \
| jq '[.results[].id]')
echo "Assigning servers: ${SERVER_IDS}"
# Assign all servers to the pool in one call
curl -s -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d "{\"servers\": ${SERVER_IDS}}" \
${MOJOHOST}/api/pool/${POOL_ID}/assign_servers/
7. Verify the Result¶
# Check the pool now has our servers
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
${MOJOHOST}/api/pool/${POOL_ID}/ | jq '{name, servers_count, description}'
# List servers in the pool with their details
curl -s -k \
-H "Authorization: Bearer ${TOKEN}" \
"${MOJOHOST}/api/server/?resource_pool=${POOL_ID}" \
| jq '.results[] | {id, name, model, manufacturer, power_state}'
Done!
You've completed a full lifecycle: authentication, credential setup, network discovery, node registration, pool creation, and server assignment — all through the API. This entire workflow can be wrapped in a script or integrated into your automation platform.
Quick Reference: Common Endpoints¶
| Action | Method | Endpoint |
|---|---|---|
| Authentication | ||
| Get API access token | POST |
/api/token/ |
| Refresh token | POST |
/api/token/refresh/ |
| Node Discovery | ||
| Create scan range | POST |
/api/node_discovery/scan_range/ |
| List scan ranges | GET |
/api/node_discovery/scan_range/ |
| Run discovery scan | POST |
/api/node_discovery/run_scan/ |
| List nodes | GET |
/api/node/ |
| Register a node | POST |
/api/node/{id}/register/ |
| Resource Pools | ||
| List pools | GET |
/api/pool/ |
| Create pool | POST |
/api/pool/ |
| Get pool details | GET |
/api/pool/{id}/ |
| Update pool | PUT |
/api/pool/{id}/ |
| Delete pool | DELETE |
/api/pool/{id}/ |
| Assign servers to pool | POST |
/api/pool/{id}/assign_servers/ |
| Assign switches to pool | POST |
/api/pool/{id}/assign_switches/ |
| Create sub-pool | POST |
/api/pool/{id}/create_sub_pool/ |
| Remove servers from pool | POST |
/api/server/remove_from_pool/ |
| Servers | ||
| List servers | GET |
/api/server/ |
| Get server details | GET |
/api/server/{id}/ |
| Update server | PATCH |
/api/server/{id}/ |
| Server processors | GET |
/api/server/{id}/processors/ |
| Server ethernet interfaces | GET |
/api/server/{id}/ethernet_interfaces/ |
| Server storage | GET |
/api/server/{id}/storages/ |
| Server firmware inventory | GET |
/api/server/{id}/firmwares/ |
| Firmware | ||
| List firmware binaries | GET |
/api/firmware/ |
| Get firmware binary | GET |
/api/firmware/{id}/ |
| Auth Profiles | ||
| List profiles | GET |
/api/node_discovery/auth_profile/ |
| Create profile | POST |
/api/node_discovery/auth_profile/ |
| List profile credentials | GET |
/api/node_discovery/auth_profile/{id}/credentials/ |
| Add credential | POST |
/api/node_discovery/auth_profile/{id}/credentials/ |
Query Parameters Reference¶
| Parameter | Description | Example |
|---|---|---|
search |
Full-text search across searchable fields | ?search=PowerEdge |
ordering |
Sort results (prefix - for descending) |
?ordering=-name |
page |
Page number for pagination | ?page=2 |
page_size |
Results per page (max 1000) | ?page_size=50 |
resource_pool |
Filter servers by pool ID | ?resource_pool=1 |
power_state |
Filter servers by power state | ?power_state=On |
status |
Filter nodes/scans by status | ?status=discovered |