{"id":51398,"date":"2025-08-07T10:24:10","date_gmt":"2025-08-07T10:24:10","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=51398"},"modified":"2025-08-07T10:24:10","modified_gmt":"2025-08-07T10:24:10","slug":"ansible-how-to-work-with-ansible-tower-rest-api-with-example","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/ansible-how-to-work-with-ansible-tower-rest-api-with-example\/","title":{"rendered":"Ansible: How to Work with Ansible Tower REST API (with Example)"},"content":{"rendered":"\n<p>Absolutely! <strong>Ansible Tower (now called Controller in AAP)<\/strong> has a robust, well-documented <strong>REST API<\/strong>. You can use it to automate everything you do via the web UI\u2014launch jobs, manage inventories, users, credentials, and more.<br>Below is a practical, step-by-step guide (with examples!) to help you get started.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>How to Work with Ansible Tower REST API (with Example)<\/strong><\/h1>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1. Understanding the Ansible Tower API<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Type:<\/strong> RESTful, JSON-based API.<\/li>\n\n\n\n<li><strong>Docs:<\/strong> Interactive Swagger\/OpenAPI docs usually at:<br><code>https:\/\/&lt;tower-server>\/api\/<\/code><br><em>(log in and try it!)<\/em><\/li>\n\n\n\n<li><strong>Authentication:<\/strong>\n<ul class=\"wp-block-list\">\n<li>Basic Auth (username\/password or Personal Access Token)<\/li>\n\n\n\n<li>OAuth2 (for advanced use cases)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>2. API Authentication<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Basic Auth:<\/strong><br>Every request uses HTTP basic authentication.<br>Example: <code>user:password<\/code> or Personal Access Token as username (no password needed).<\/li>\n\n\n\n<li><strong>Getting a Token:<\/strong><br>In Tower UI:<br><strong>User \u2192 Tokens \u2192 Create Token<\/strong><br>(Recommended: use tokens for automation!)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3. Making a Simple API Request<\/strong><\/h2>\n\n\n\n<p>Let\u2019s say your Tower UI is at <code>https:\/\/13.233.139.133\/<\/code>.<\/p>\n\n\n\n<p><strong>List all Job Templates (curl):<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">curl -k -u <span class=\"hljs-string\">'admin:yourpassword'<\/span> https:<span class=\"hljs-comment\">\/\/13.233.139.133\/api\/v2\/job_templates\/<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li><code>-k<\/code>: Allow insecure (self-signed) SSL<\/li>\n\n\n\n<li><code>-u<\/code>: Basic auth, <code>'user:password'<\/code><\/li>\n\n\n\n<li>The response is JSON<\/li>\n<\/ul>\n\n\n\n<p><strong>Using a Personal Access Token (PAT):<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">curl -k -H <span class=\"hljs-string\">\"Authorization: Bearer &lt;your_token&gt;\"<\/span> https:<span class=\"hljs-comment\">\/\/13.233.139.133\/api\/v2\/job_templates\/<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>4. Example: Launch a Job Template via API<\/strong><\/h2>\n\n\n\n<p>Suppose you have a job template with <strong>ID 7<\/strong>.<\/p>\n\n\n\n<p><strong>API URL:<\/strong><br><code>POST \/api\/v2\/job_templates\/7\/launch\/<\/code><\/p>\n\n\n\n<p><strong>Example (with token):<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">curl -k -H <span class=\"hljs-string\">\"Authorization: Bearer &lt;your_token&gt;\"<\/span> \\\n     -X POST https:<span class=\"hljs-comment\">\/\/13.233.139.133\/api\/v2\/job_templates\/7\/launch\/<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>The response includes the <strong>job ID<\/strong> (e.g., <code>\"id\": 81<\/code>).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>5. Check Job Status<\/strong><\/h2>\n\n\n\n<p>Suppose your launched job returned <code>\"id\": 81<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">curl -k -H <span class=\"hljs-string\">\"Authorization: Bearer &lt;your_token&gt;\"<\/span> \\\n     <span class=\"hljs-attr\">https<\/span>:<span class=\"hljs-comment\">\/\/13.233.139.133\/api\/v2\/jobs\/81\/<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Look for <code>\"status\": \"successful\"<\/code> (other states: &#8220;pending&#8221;, &#8220;running&#8221;, &#8220;failed&#8221;).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>6. See Job Output (Standard Out)<\/strong><\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">curl -k -H <span class=\"hljs-string\">\"Authorization: Bearer &lt;your_token&gt;\"<\/span> \\\n     <span class=\"hljs-attr\">https<\/span>:<span class=\"hljs-comment\">\/\/13.233.139.133\/api\/v2\/jobs\/81\/stdout\/?format=txt<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Add <code>?format=txt<\/code> or <code>?format=html<\/code> as needed.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>7. Example: Create an Inventory via API<\/strong><\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">curl -k -H <span class=\"hljs-string\">\"Authorization: Bearer &lt;your_token&gt;\"<\/span> \\\n     -H <span class=\"hljs-string\">\"Content-Type: application\/json\"<\/span> \\\n     -d <span class=\"hljs-string\">'{\"name\":\"TestInventory\",\"organization\":1}'<\/span> \\\n     -X POST https:<span class=\"hljs-comment\">\/\/13.233.139.133\/api\/v2\/inventories\/<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Replace <code>organization: 1<\/code> with your organization\u2019s ID (list orgs via <code>\/api\/v2\/organizations\/<\/code>).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>8. Useful Endpoints<\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>API Endpoint<\/th><th>Description<\/th><\/tr><\/thead><tbody><tr><td><code>\/api\/v2\/<\/code><\/td><td>API root &amp; docs<\/td><\/tr><tr><td><code>\/api\/v2\/job_templates\/<\/code><\/td><td>List\/create job templates<\/td><\/tr><tr><td><code>\/api\/v2\/job_templates\/&lt;id&gt;\/launch\/<\/code><\/td><td>Launch a job template<\/td><\/tr><tr><td><code>\/api\/v2\/jobs\/&lt;id&gt;\/<\/code><\/td><td>Check job status\/details<\/td><\/tr><tr><td><code>\/api\/v2\/jobs\/&lt;id&gt;\/stdout\/<\/code><\/td><td>Get job standard output<\/td><\/tr><tr><td><code>\/api\/v2\/inventories\/<\/code><\/td><td>List\/create inventories<\/td><\/tr><tr><td><code>\/api\/v2\/hosts\/<\/code><\/td><td>List\/create hosts<\/td><\/tr><tr><td><code>\/api\/v2\/credentials\/<\/code><\/td><td>List\/create credentials<\/td><\/tr><tr><td><code>\/api\/v2\/users\/<\/code><\/td><td>List\/create users<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>9. Example Python Script (requests library)<\/strong><\/h2>\n\n\n\n<p>Here\u2019s a simple Python snippet to <strong>list all job templates<\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">import requests\n\napi_url = <span class=\"hljs-string\">\"https:\/\/13.233.139.133\/api\/v2\/job_templates\/\"<\/span>\ntoken = <span class=\"hljs-string\">\"&lt;your_token&gt;\"<\/span>  <span class=\"hljs-comment\"># Or use user\/pass in auth param<\/span>\n\nheaders = {\n    <span class=\"hljs-string\">\"Authorization\"<\/span>: f<span class=\"hljs-string\">\"Bearer {token}\"<\/span>,\n    <span class=\"hljs-string\">\"Content-Type\"<\/span>: <span class=\"hljs-string\">\"application\/json\"<\/span>\n}\n\nresponse = requests.get(api_url, headers=headers, verify=<span class=\"hljs-keyword\">False<\/span>)\n<span class=\"hljs-keyword\">for<\/span> jt in response.json()&#91;<span class=\"hljs-string\">'results'<\/span>]:\n    <span class=\"hljs-keyword\">print<\/span>(f<span class=\"hljs-string\">\"ID: {jt&#91;'id']}, Name: {jt&#91;'name']}\"<\/span>)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><em>(use <code>verify=False<\/code> for self-signed SSL)<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>10. Finding More API Endpoints and Docs<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Visit: <code>https:\/\/&lt;tower-server>\/api\/<\/code> in your browser<\/li>\n\n\n\n<li>Try out requests in Swagger UI<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Summary Table<\/strong><\/h1>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Action<\/th><th>HTTP Method<\/th><th>API URL<\/th><th>Notes<\/th><\/tr><\/thead><tbody><tr><td>List job templates<\/td><td>GET<\/td><td><code>\/api\/v2\/job_templates\/<\/code><\/td><td><\/td><\/tr><tr><td>Launch a job template<\/td><td>POST<\/td><td><code>\/api\/v2\/job_templates\/&lt;id&gt;\/launch\/<\/code><\/td><td>Needs job template ID<\/td><\/tr><tr><td>Check job status<\/td><td>GET<\/td><td><code>\/api\/v2\/jobs\/&lt;id&gt;\/<\/code><\/td><td><\/td><\/tr><tr><td>Get job output<\/td><td>GET<\/td><td><code>\/api\/v2\/jobs\/&lt;id&gt;\/stdout\/?format=txt<\/code><\/td><td><\/td><\/tr><tr><td>Create inventory<\/td><td>POST<\/td><td><code>\/api\/v2\/inventories\/<\/code><\/td><td>JSON body needed<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Tips and Best Practices<\/strong><\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <strong>Personal Access Tokens<\/strong> for CI\/CD or scripts (not passwords).<\/li>\n\n\n\n<li>Always use HTTPS for security.<\/li>\n\n\n\n<li>Use the <code>\/api\/<\/code> browser docs for full details and live \u201ctry it now\u201d features.<\/li>\n\n\n\n<li>Automate with Python (<code>requests<\/code>), Bash (<code>curl<\/code>), or your favorite language.<\/li>\n\n\n\n<li>Respect rate limits and error messages\u2014read the <code>\"detail\"<\/code> field in API responses for helpful info.<\/li>\n\n\n\n<li>For bulk\/complex changes, look at <a href=\"https:\/\/docs.ansible.com\/ansible-tower\/latest\/html\/towercli\/index.html\" target=\"_blank\" rel=\"noopener\">tower-cli (deprecated, now awx-cli)<\/a> or the newer <code>awx<\/code> CLI tool.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Absolutely! Ansible Tower (now called Controller in AAP) has a robust, well-documented REST API. You can use it to automate everything you do via the web UI\u2014launch jobs, manage inventories,&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-51398","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/51398","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=51398"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/51398\/revisions"}],"predecessor-version":[{"id":51399,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/51398\/revisions\/51399"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=51398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=51398"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=51398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}