April 20, 2026

Authenticating with Jira Cloud APIs to Create and Fetch Issues

🚀 End-to-End Guide: Authenticating with Jira Cloud APIs to Create and Fetch Issues

Integrating with Jira Cloud programmatically is a common requirement for automation, testing, and DevOps workflows. This guide walks through the complete authentication flow using OAuth (client credentials) and demonstrates how to fetch and create Jira issues using REST APIs.

This approach is designed for non-interactive service integrations, meaning no UI login is required.


🔐 Overview of the Flow

At a high level, interacting with Jira APIs involves four key steps:

  1. Generate an access token
  2. Discover accessible resources (Cloud ID)
  3. Fetch existing issues
  4. Create new issues

Each step builds on the previous one.


1️⃣ Generate an Access Token

Authentication begins by exchanging your client credentials for an access token.

Pre-requisites

  1. Create a service user in Atlassian Jira directory.
  2. Create an OAuth 2.0 credentials to get the Client ID and Client Credentials.

Request

POST https://auth.atlassian.com/oauth/token
Content-Type: application/json

Body

{
  "grant_type": "client_credentials",
  "client_id": "{{CLIENT_ID}}",
  "client_secret": "{{CLIENT_SECRET}}",
  "audience": "api.atlassian.com"
}

This returns a response containing:

{
  "access_token": "your_token_here",
  "expires_in": 3600
}



You’ll use this access_token for all subsequent API calls.  


2️⃣ Retrieve Cloud ID (Accessible Resources)

Jira APIs require a Cloud ID, which identifies the Jira instance associated with your token.

Request

GET https://api.atlassian.com/oauth/token/accessible-resources
Authorization: Bearer {{ACCESS_TOKEN}}
Accept: application/json

Response

[
  {
    "id": "cloud-id",
    "url": "https://your-instance.atlassian.net"
  }
]
  • id → used as cloudId
  • url → base Jira site URL



This step is essential because all Jira API calls must go through the API gateway using the Cloud ID.  


3️⃣ Fetch a Jira Issue

Once authenticated, you can retrieve issue details.

Request

GET https://api.atlassian.com/ex/jira/{{CLOUD_ID}}/rest/api/3/issue/{{PROJECT_KEY}}-1
Authorization: Bearer {{ACCESS_TOKEN}}
Accept: application/json

What this does

  • Uses the API gateway (api.atlassian.com)
  • Authenticates with Bearer token
  • Fetches a specific issue using its key



This endpoint returns full issue details including summary, status, and metadata.  


4️⃣ Create a Jira Issue

Creating issues programmatically is one of the most common use cases.

Request

POST https://api.atlassian.com/ex/jira/{{CLOUD_ID}}/rest/api/3/issue
Authorization: Bearer {{ACCESS_TOKEN}}
Accept: application/json
Content-Type: application/json

Body

{
  "fields": {
    "project": {
      "key": "{{PROJECT_KEY}}"
    },
    "summary": "Bug created from API",
    "description": {
      "type": "doc",
      "version": 1,
      "content": [
        {
          "type": "paragraph",
          "content": [
            {
              "type": "text",
              "text": "Created via API using OAuth token"
            }
          ]
        }
      ]
    },
    "issuetype": {
      "name": "Bug"
    }
  }
}

Important Notes

  • Description must use Atlassian Document Format (ADF) — plain text is not accepted.
  • project.key must exist in your Jira instance.
  • issuetype.name must be valid (e.g., Bug, Task, Story).



This request creates a new issue and returns its ID and key.  


🔁 Automating the Flow

In tools like Bruno or Postman, you can automate this workflow:

  • Store access_token after token request
  • Extract cloudId dynamically
  • Reuse both in subsequent requests

Example script:

const body = bru.response.json();
bru.setEnvVar("ACCESS_TOKEN", body.access_token);

⚠️ Common Pitfalls

❌ Using the wrong base URL

  • Don’t use: https://your-domain.atlassian.net/rest/api/...
  • Use: https://api.atlassian.com/ex/jira/{cloudId}/...

❌ Missing permissions

  • The service account must have:
    • Browse Projects
    • Create Issues (for POST)

❌ Invalid payload

  • Missing required fields → 400 error
  • Wrong issue type → validation failure

❌ Expired token

  • Tokens expire (usually in 1 hour)
  • Regenerate as needed

🧩 Putting It All Together

Here’s the complete sequence:

  1. 🔑 Get access token
  2. 🌐 Get Cloud ID
  3. 📥 Fetch issue
  4. 📤 Create issue

This workflow enables full read/write automation with Jira Cloud APIs.


🏁 Conclusion

Using OAuth with client credentials provides a secure and scalable way to interact with Jira Cloud APIs without relying on user login or UI access.

With just a few API calls, you can:

  • integrate Jira into CI/CD pipelines
  • automate bug creation
  • build dashboards or monitoring tools

Once set up, this becomes a powerful foundation for any Jira-based automation.


Please feel free to reachout psrdotcom@gmail.com for any feedback and suggestions.

January 30, 2026

Making a Local Dev Server accessible via Public Domain using Cloudflare Tunnel

Hi all,

Today, we are going to discuss how you can publicly access the local running server with a domain and Cloudflare tunnel.

Pre-requisites

  1. Domain
  2. DNS on Cloudflare
  3. Cloudflare One account access
  4. Local server

Set up the environment

Application

Make sure your application runs locally on a port like 8000,9000 etc.

Cloudflare Tunnel

  1. Log in to your Cloudflare One account.
  2. Go to "Zero Trust".
  3. Expand Networks and select Connectors.
  4. Click on “Create a tunnel”.
  5. Select “Cloudflared”.
  6. Give a name to your tunnel.
  7. Click on “Save”.
  8. In the "Choose your environment" section, select the environment where the server is running.
  9. Follow the instructions to install and run a connector.
  10. Here, you need to move to your server machine.
  11. Open the terminal and perform the instructions to install the "cloudflared" tool.
  12. Run using the token (part of the command).
  13. Once the installation is completed. Click on Save.

Add IP/CIDR

  1. Edit the tunnel to add the IP/CIDR.
  2. Choose based on your local DHCP.

Published application routes

  1. Click on “Add a published application route”.
  2. Give an optional subdomain.
  3. Select the domain from the dropdown.
    1. You need to have your domain managed by Cloudflare (DNS).
  4. An optional path to make sure you have a frontend and a backend that work together.
  5. Under service, select Type as HTTP, and your local machine server port.
  6. Select the URL of the server application, including the localport.
    1. localhost:9000
  7. Click on “Save”.
Note: If you have a frontend and a backend, then you need to add one more application route.

In my scenario, the frontend path is * with localhost:9001, and the backend path is api/* with localhost:8000.

Run the tunnel

  1. Make sure your local web server is running
  2. Log in to cloudflared
    • cloudflared tunnel login
    • Authorize the tunnel on the web browser post login
  3. List the tunnels
    • cloudflared tunnel list
  4. Get the tunnel token from the tunnel you created in Cloudflare connectors
  5. Run the command on the local terminal
    • cloudflared tunnel run --token eyJhIjoiM2...
  6. Now, you should be able to browse your configured subdomain with your local web server content. 

Troubleshooted issue

If the frontend with path "/*" is above the backend route, then your backend APIs will never be reached.

So, "move up" the backend with "/api/*" path above the frontend to serve the requests.

Feel free to reach out to me if you have any doubts and clarifications needed at my email psrdotcom@gmail.com


Featured Post

Java Introdcution

Please send your review and feedback to psrdotcom@gmail.com