Skip to main content

Overview

Jobs are instances of job templates that have been launched. They represent the execution of an Ansible playbook with specific parameters. Jobs are read-only except for cancellation.

Endpoints

MethodEndpointDescription
GET/api/v2/jobs/List jobs
GET/api/v2/jobs/{id}/Retrieve job details
POST/api/v2/jobs/{id}/cancel/Cancel running job
POST/api/v2/jobs/{id}/relaunch/Relaunch job
GET/api/v2/jobs/{id}/stdout/Get job output
GET/api/v2/jobs/{id}/job_events/List job events

List Jobs

curl -X GET \
  https://awx.example.com/api/v2/jobs/ \
  -H "Authorization: Bearer YOUR_TOKEN"
status
string
Filter by status: new, pending, waiting, running, successful, failed, error, canceled
job_type
string
Filter by type: run or check

Retrieve Job

curl -X GET \
  https://awx.example.com/api/v2/jobs/123/ \
  -H "Authorization: Bearer YOUR_TOKEN"

Response Schema

id
integer
Job ID
name
string
Job name (from template)
description
string
Job description
job_type
string
Job type: run or check
status
string
Current status: new, pending, waiting, running, successful, failed, error, canceled
failed
boolean
Whether job failed
started
string
Start timestamp
finished
string
Completion timestamp
canceled_on
string
Cancellation timestamp
elapsed
number
Elapsed time in seconds
job_explanation
string
Explanation for job status
execution_node
string
Node where job executed
controller_node
string
Controller node
launch_type
string
How job was launched: manual, relaunch, callback, scheduled, dependency, workflow, webhook, sync, scm
playbook
string
Playbook that was executed
scm_revision
string
SCM revision used
scm_branch
string
SCM branch used
inventory
integer
Inventory ID
project
integer
Project ID
job_template
integer
Job template ID
limit
string
Host limit
extra_vars
string
Extra variables (displayed, sensitive values hidden)
artifacts
object
Artifacts set by the job
forks
integer
Number of forks used
verbosity
integer
Verbosity level
job_tags
string
Tags applied
skip_tags
string
Tags skipped
timeout
integer
Job timeout
diff_mode
boolean
Whether diff mode was enabled
use_fact_cache
boolean
Whether fact cache was used
allow_simultaneous
boolean
Whether simultaneous execution is allowed
job_slice_number
integer
Slice number (for distributed jobs)
job_slice_count
integer
Total number of slices
webhook_service
string
Webhook service that triggered job
webhook_guid
string
Webhook GUID
Links to related resources:
  • job_template - Source template
  • inventory - Job inventory
  • project - Source project
  • execution_environment - Execution environment
  • credentials - Credentials used
  • labels - Job labels
  • job_events - Playbook events
  • job_host_summaries - Host summaries
  • activity_stream - Activity log
  • notifications - Notifications sent
  • cancel - Cancel endpoint
  • relaunch - Relaunch endpoint
  • create_schedule - Create schedule from job

Job Output

Get Standard Output

curl -X GET \
  https://awx.example.com/api/v2/jobs/123/stdout/ \
  -H "Authorization: Bearer YOUR_TOKEN"
Returns full Ansible playbook output.

Get Formatted Output

curl -X GET \
  "https://awx.example.com/api/v2/jobs/123/stdout/?format=txt" \
  -H "Authorization: Bearer YOUR_TOKEN"
format
string
default:"html"
Output format: html, txt, ansi, json
download
boolean
Download as file attachment

Job Events

List detailed playbook events:
curl -X GET \
  https://awx.example.com/api/v2/jobs/123/job_events/ \
  -H "Authorization: Bearer YOUR_TOKEN"
Events include:
  • playbook_on_start
  • playbook_on_play_start
  • playbook_on_task_start
  • runner_on_ok
  • runner_on_failed
  • runner_on_skipped
  • runner_on_unreachable
  • playbook_on_stats
  • And many more…

Children Summary

curl -X GET \
  https://awx.example.com/api/v2/jobs/123/job_events/children_summary/ \
  -H "Authorization: Bearer YOUR_TOKEN"

Job Host Summaries

Get per-host execution summary:
curl -X GET \
  https://awx.example.com/api/v2/jobs/123/job_host_summaries/ \
  -H "Authorization: Bearer YOUR_TOKEN"
Response includes per-host:
  • ok - Successful tasks
  • changed - Tasks that made changes
  • dark - Unreachable hosts
  • failures - Failed tasks
  • skipped - Skipped tasks

Cancel Job

Cancel a running or pending job:
curl -X POST \
  https://awx.example.com/api/v2/jobs/123/cancel/ \
  -H "Authorization: Bearer YOUR_TOKEN"
Only jobs in new, pending, waiting, or running status can be canceled.

Relaunch Job

Relaunch a job with the same parameters:
curl -X POST \
  https://awx.example.com/api/v2/jobs/123/relaunch/ \
  -H "Authorization: Bearer YOUR_TOKEN"
Returns a new job object.

Create Schedule from Job

curl -X POST \
  https://awx.example.com/api/v2/jobs/123/create_schedule/ \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Daily Deploy",
    "description": "Deploy daily at 2 AM",
    "rrule": "DTSTART:20240101T020000Z RRULE:FREQ=DAILY;INTERVAL=1"
  }'

Job Labels

curl -X GET \
  https://awx.example.com/api/v2/jobs/123/labels/ \
  -H "Authorization: Bearer YOUR_TOKEN"

Job Notifications

curl -X GET \
  https://awx.example.com/api/v2/jobs/123/notifications/ \
  -H "Authorization: Bearer YOUR_TOKEN"

Activity Stream

curl -X GET \
  https://awx.example.com/api/v2/jobs/123/activity_stream/ \
  -H "Authorization: Bearer YOUR_TOKEN"

Filtering Jobs

# By status
?status=successful
?status__in=pending,waiting,running

# By job type
?job_type=run

# By template
?job_template=10

# By inventory
?inventory=3

# By project
?project=5

# By date range
?created__gte=2024-01-01
?finished__lte=2024-12-31

# Failed jobs
?failed=true

# By launch type
?launch_type=scheduled

# By playbook
?playbook=site.yml

Ordering

# By start time (most recent first)
?order_by=-started

# By finish time
?order_by=-finished

# By status
?order_by=status

# By elapsed time
?order_by=-elapsed

Monitoring Running Jobs

Poll Job Status

import requests
import time

base_url = "https://awx.example.com/api/v2"
token = "YOUR_TOKEN"
job_id = 123

while True:
    response = requests.get(
        f"{base_url}/jobs/{job_id}/",
        headers={"Authorization": f"Bearer {token}"}
    )
    
    job = response.json()
    status = job['status']
    
    print(f"Status: {status}, Elapsed: {job.get('elapsed', 0)}s")
    
    if status in ['successful', 'failed', 'error', 'canceled']:
        print(f"Job finished: {status}")
        break
    
    time.sleep(2)

Stream Job Events

import requests

base_url = "https://awx.example.com/api/v2"
token = "YOUR_TOKEN"
job_id = 123

# Get events with limit for real-time streaming
url = f"{base_url}/jobs/{job_id}/job_events/?order_by=counter"
headers = {"Authorization": f"Bearer {token}"}

last_counter = 0

while True:
    response = requests.get(
        f"{url}&counter__gt={last_counter}",
        headers=headers
    )
    
    data = response.json()
    events = data.get('results', [])
    
    for event in events:
        print(f"[{event['event']}] {event.get('stdout', '')}")
        last_counter = max(last_counter, event['counter'])
    
    if not events:
        # Check if job is done
        job = requests.get(
            f"{base_url}/jobs/{job_id}/",
            headers=headers
        ).json()
        
        if job['status'] not in ['pending', 'waiting', 'running']:
            break
    
    time.sleep(1)

Job Statistics

Jobs track execution statistics:
{
  "ok": 12,
  "changed": 5,
  "dark": 0,
  "failures": 0,
  "skipped": 3,
  "rescued": 0,
  "ignored": 0
}
These are available in the job detail response and in job_host_summaries.

Complete Example

import requests
import json
import time

base_url = "https://awx.example.com/api/v2"
token = "YOUR_TOKEN"
headers = {
    "Authorization": f"Bearer {token}",
    "Content-Type": "application/json"
}

# Launch job from template
launch_response = requests.post(
    f"{base_url}/job_templates/10/launch/",
    headers=headers,
    data=json.dumps({"limit": "web*"})
)

if launch_response.status_code in [201, 202]:
    job = launch_response.json()
    job_id = job['id']
    print(f"Launched job {job_id}")
    
    # Monitor job
    while True:
        job_response = requests.get(
            f"{base_url}/jobs/{job_id}/",
            headers=headers
        )
        job = job_response.json()
        
        print(f"Status: {job['status']}, Elapsed: {job.get('elapsed', 0)}s")
        
        if job['status'] in ['successful', 'failed', 'error', 'canceled']:
            print(f"\\nJob {job['status']}")
            
            # Get summary
            if job['status'] == 'successful':
                summaries = requests.get(
                    f"{base_url}/jobs/{job_id}/job_host_summaries/",
                    headers=headers
                ).json()
                
                print(f"Hosts processed: {summaries['count']}")
                for summary in summaries['results']:
                    host = summary['summary_fields']['host']['name']
                    print(f"  {host}: ok={summary['ok']}, changed={summary['changed']}, failed={summary['failures']}")
            
            # Get output
            stdout = requests.get(
                f"{base_url}/jobs/{job_id}/stdout/?format=txt",
                headers=headers
            ).text
            
            print(f"\\nOutput:\\n{stdout[:500]}...")
            
            break
        
        time.sleep(3)
else:
    print(f"Error launching job: {launch_response.status_code}")
    print(launch_response.json())

Build docs developers (and LLMs) love