| name | jira |
| description | Jira Cloud REST API via curl. Use this skill to create, update, search, and manage issues, projects, and workflows in Jira. |
| vm0_secrets | JIRA_API_TOKEN |
| vm0_vars | JIRA_DOMAIN, JIRA_EMAIL |
Jira API
Use the Jira Cloud REST API via direct curl calls to manage issues, projects, and workflows.
Official docs:
https://developer.atlassian.com/cloud/jira/platform/rest/v3/
When to Use
Use this skill when you need to:
- Create issues in Jira projects
- Search issues using JQL (Jira Query Language)
- Update issues (status, assignee, priority, etc.)
- Get issue details and comments
- List projects and their metadata
- Transition issues through workflow states
- Add comments to issues
Prerequisites
- Go to Atlassian Account Settings
- Click Create API token
- Copy the generated token (you won't see it again)
export JIRA_DOMAIN="mycompany" # e.g., "mycompany" or "mycompany.atlassian.net"
export JIRA_EMAIL="you@example.com" # Your Atlassian account email
export JIRA_API_TOKEN="your-api-token" # API token from step 2
Rate Limits
Jira Cloud has rate limits that vary by endpoint. For most REST API calls, expect limits around 100-500 requests per minute.
Important: When using
$VARin a command that pipes to another command, wrap the command containing$VARinbash -c '...'. Due to a Claude Code bug, environment variables are silently cleared when pipes are used directly.bash -c 'curl -s "https://api.example.com" -H "Authorization: Bearer $API_KEY"' | jq .
How to Use
All examples below assume JIRA_DOMAIN, JIRA_EMAIL, and JIRA_API_TOKEN are set.
Base URL: https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3
Note:
${JIRA_DOMAIN%.atlassian.net}strips the suffix if present, so bothmycompanyandmycompany.atlassian.network.
1. Get Current User
Verify your authentication:
bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/myself" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"' | jq '{accountId, emailAddress, displayName, active}
2. List Projects
Get all projects you have access to:
bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/project" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"' | jq '.[] | {id, key, name}
3. Get Project Details
Get details for a specific project:
PROJECT_KEY="PROJ"
bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/project/${PROJECT_KEY}" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"' | jq '{id, key, name, projectTypeKey, lead: .lead.displayName}
4. Get Issue Types for Project
List available issue types (Task, Bug, Story, etc.):
PROJECT_KEY="PROJ"
bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/project/${PROJECT_KEY}" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"' | jq '.issueTypes[] | {id, name, subtask}
5. Search Issues with JQL
Search issues using Jira Query Language:
Write to /tmp/jira_request.json:
{
"jql": "project = PROJ AND status NOT IN (Done) ORDER BY created DESC",
"maxResults": 10,
"fields": ["key", "summary", "status", "assignee", "priority"]
}
Then run:
bash -c 'curl -s -X POST "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/search/jql" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json' | jq '.issues[] | {key, summary: .fields.summary, status: .fields.status.name, assignee: .fields.assignee.displayName, priority: .fields.priority.name}'
Common JQL examples:
project = PROJ- Issues in projectassignee = currentUser()- Your issuesstatus = "In Progress"- By statusstatus NOT IN (Done, Closed)- Exclude statusescreated >= -7d- Created in last 7 dayslabels = bug- By labelpriority = High- By priority
6. Get Issue Details
Get full details of an issue:
ISSUE_KEY="PROJ-123"
bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"' | jq '{key, summary: .fields.summary, status: .fields.status.name, assignee: .fields.assignee.displayName, priority: .fields.priority.name, created: .fields.created, updated: .fields.updated}
7. Create Issue
Create a new issue (API v3 uses Atlassian Document Format for description):
Write to /tmp/jira_request.json:
{
"fields": {
"project": {"key": "PROJ"},
"summary": "Bug: Login button not responding",
"description": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": "The login button on the mobile app is not responding when tapped."}
]
}
]
},
"issuetype": {"name": "Bug"}
}
}
Then run:
bash -c 'curl -s -X POST "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json' | jq '{id, key, self}'
8. Create Issue with Priority and Labels
Create issue with additional fields:
Write to /tmp/jira_request.json:
{
"fields": {
"project": {"key": "PROJ"},
"summary": "Implement user authentication",
"description": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": "Add OAuth2 authentication flow for the mobile app."}
]
}
]
},
"issuetype": {"name": "Story"},
"priority": {"name": "High"},
"labels": ["backend", "security"]
}
}
Then run:
bash -c 'curl -s -X POST "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json' | jq '{id, key, self}'
9. Update Issue
Update an existing issue:
ISSUE_KEY="PROJ-123"
Write to /tmp/jira_request.json:
{
"fields": {
"summary": "Updated: Login button not responding on iOS",
"priority": {"name": "Highest"},
"labels": ["bug", "ios", "urgent"]
}
}
Then run:
bash -c 'curl -s -X PUT "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json'
Returns 204 No Content on success.
10. Get Available Transitions
Get possible status transitions for an issue:
ISSUE_KEY="PROJ-123"
bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}/transitions" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"' | jq '.transitions[] | {id, name, to: .to.name}
11. Transition Issue (Change Status)
Move issue to a different status:
ISSUE_KEY="PROJ-123"
TRANSITION_ID="31" # Get from transitions endpoint
Write to /tmp/jira_request.json:
{
"transition": {
"id": "${TRANSITION_ID}"
}
}
Then run:
bash -c 'curl -s -X POST "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}/transitions" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json'
Returns 204 No Content on success.
12. Add Comment
Add a comment to an issue:
ISSUE_KEY="PROJ-123"
Write to /tmp/jira_request.json:
{
"body": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": "Investigated and found the root cause. Working on a fix."}
]
}
]
}
}
Then run:
bash -c 'curl -s -X POST "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}/comment" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json' | jq '{id, created, author: .author.displayName}'
13. Get Issue Comments
List all comments on an issue:
ISSUE_KEY="PROJ-123"
bash -c 'curl -s -X GET "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}/comment" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json"' | jq '.comments[] | {id, author: .author.displayName, created, body: .body.content[0].content[0].text}
14. Assign Issue
Assign an issue to a user:
ISSUE_KEY="PROJ-123"
ACCOUNT_ID="5b10ac8d82e05b22cc7d4ef5" # Get from /rest/api/3/user/search
Write to /tmp/jira_request.json:
{
"accountId": "${ACCOUNT_ID}"
}
Then run:
bash -c 'curl -s -X PUT "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}/assignee" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" -d @/tmp/jira_request.json'
15. Search Users
Find users by email or name:
bash -c 'curl -s -G "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/user/search" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}" --header "Accept: application/json" --data-urlencode "query=john"' | jq '.[] | {accountId, displayName, emailAddress}
16. Delete Issue
Delete an issue (use with caution):
ISSUE_KEY="PROJ-123"
curl -s -X DELETE "https://${JIRA_DOMAIN%.atlassian.net}.atlassian.net/rest/api/3/issue/${ISSUE_KEY}" -u "${JIRA_EMAIL}:${JIRA_API_TOKEN}"
Returns 204 No Content on success.
Atlassian Document Format (ADF)
Jira API v3 uses ADF for rich text fields like description and comment.body. Basic structure:
{
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": "Plain text"},
{"type": "text", "text": "Bold text", "marks": [{"type": "strong"}]},
{"type": "text", "text": "Code", "marks": [{"type": "code"}]}
]
},
{
"type": "bulletList",
"content": [
{"type": "listItem", "content": [{"type": "paragraph", "content": [{"type": "text", "text": "Item 1"}]}]},
{"type": "listItem", "content": [{"type": "paragraph", "content": [{"type": "text", "text": "Item 2"}]}]}
]
},
{
"type": "codeBlock",
"attrs": {"language": "python"},
"content": [{"type": "text", "text": "print('hello')"}]
}
]
}
Guidelines
- Use JQL for complex queries: JQL is powerful for filtering issues by any field combination
- Check transitions first: Before changing status, get available transitions for the issue
- Handle pagination: Use
startAtandmaxResultsfor large result sets - Use account IDs: Jira Cloud uses account IDs (not usernames) for user references
- ADF for rich text: API v3 requires Atlassian Document Format for description and comments
- Rate limiting: Implement exponential backoff if you receive 429 responses