Install
openclaw skills install jira-apiJira API integration with managed OAuth. Search issues with JQL, create and update issues, manage projects and transitions. Use this skill when users want to interact with Jira issues, projects, or workflows. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
openclaw skills install jira-apiAccess the Jira Cloud API with managed OAuth authentication. Search issues with JQL, create and manage issues, and automate workflows.
CLI:
maton jira issue search 'project = PROJ AND status = "In Progress"' --cloud-id abc-123
maton api '/jira/ex/jira/{cloudId}/rest/api/3/search/jql?jql=project%3DKEY&maxResults=10'
Python:
# First, get your cloud ID
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/jira/oauth/token/accessible-resources')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
# Then search issues
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/jira/ex/jira/{cloudId}/rest/api/3/search/jql?jql=project%3DKEY&maxResults=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/jira/{native-api-path}
Maton proxies requests to api.atlassian.com and automatically injects your OAuth token.
Jira Cloud requires a cloud ID. Get it first:
GET /jira/oauth/token/accessible-resources
Example:
maton jira cloud list
Response:
[{
"id": "62909843-b784-4c35-b770-e4e2a26f024b",
"url": "https://yoursite.atlassian.net",
"name": "yoursite"
}]
NPM:
npm install -g @maton-ai/cli
Homebrew:
brew install maton-ai/cli/maton
CLI:
maton login # Opens browser for API key
maton login --interactive # Skip browser, paste API key directly
maton whoami # Show current auth state
Manual:
MATON_API_KEY:export MATON_API_KEY="YOUR_API_KEY"
Manage your Jira OAuth connections at https://api.maton.ai.
CLI:
maton connection list jira --status ACTIVE
maton api -X GET /connections -f app=jira -f status=ACTIVE
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=jira&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
CLI:
maton connection create jira
maton api /connections -f app=jira
Python:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'jira'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
CLI:
maton connection view {connection_id}
maton api /connections/{connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2025-12-08T07:20:53.488460Z",
"last_updated_time": "2026-01-31T20:03:32.593153Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "jira",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
CLI:
maton connection delete {connection_id}
maton api -X DELETE /connections/{connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple Jira connections, specify which one to use:
CLI:
maton jira project list --cloud-id abc-123 --connection {connection_id}
maton api /jira/ex/jira/{cloudId}/rest/api/3/project --connection {connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/jira/ex/jira/{cloudId}/rest/api/3/project')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always specify the connection to ensure requests go to the intended account.
GET /jira/ex/jira/{cloudId}/rest/api/3/project
Example:
maton jira project list --cloud-id abc-123
GET /jira/ex/jira/{cloudId}/rest/api/3/project/{projectKeyOrId}
Example:
maton jira project view PROJ --cloud-id abc-123
GET /jira/ex/jira/{cloudId}/rest/api/3/search/jql?jql=project%3DPROJ%20order%20by%20created%20DESC&maxResults=20&fields=summary,status,assignee
Example:
maton jira issue search 'project = PROJ order by created DESC' --cloud-id abc-123 --limit 20 --fields summary,status,assignee
GET /jira/ex/jira/{cloudId}/rest/api/3/issue/{issueIdOrKey}
Example:
maton jira issue view PROJ-123 --cloud-id abc-123
POST /jira/ex/jira/{cloudId}/rest/api/3/issue
Content-Type: application/json
{
"fields": {
"project": {"key": "PROJ"},
"summary": "Fix login",
"issuetype": {"name": "Task"}
}
}
Example:
maton jira issue create --cloud-id abc-123 --project PROJ --summary 'Fix login' --type Task
PUT /jira/ex/jira/{cloudId}/rest/api/3/issue/{issueIdOrKey}
Content-Type: application/json
{
"fields": {
"summary": "Updated summary"
}
}
Example:
maton jira issue update PROJ-123 --cloud-id abc-123 --summary 'Updated summary'
DELETE /jira/ex/jira/{cloudId}/rest/api/3/issue/{issueIdOrKey}
Example:
maton jira issue delete PROJ-123 --cloud-id abc-123
PUT /jira/ex/jira/{cloudId}/rest/api/3/issue/{issueIdOrKey}/assignee
Content-Type: application/json
{
"accountId": "712020:5aff718e-6fe0-4548-82f4-f44ec481e5e7"
}
Example:
maton jira issue update PROJ-123 --cloud-id abc-123 --assignee 712020:5aff718e-6fe0-4548-82f4-f44ec481e5e7
GET /jira/ex/jira/{cloudId}/rest/api/3/issue/{issueIdOrKey}/transitions
Example:
maton jira transition list PROJ-123 --cloud-id abc-123
POST /jira/ex/jira/{cloudId}/rest/api/3/issue/{issueIdOrKey}/transitions
Content-Type: application/json
{
"transition": {"id": "31"}
}
Example:
maton jira transition apply PROJ-123 --cloud-id abc-123 --id 31
GET /jira/ex/jira/{cloudId}/rest/api/3/issue/{issueIdOrKey}/comment
Example:
maton jira comment list PROJ-123 --cloud-id abc-123
POST /jira/ex/jira/{cloudId}/rest/api/3/issue/{issueIdOrKey}/comment
Content-Type: application/json
{
"body": {
"type": "doc",
"version": 1,
"content": [{"type": "paragraph", "content": [{"type": "text", "text": "Comment text"}]}]
}
}
Example:
maton jira comment add PROJ-123 --cloud-id abc-123 --body 'Comment text'
GET /jira/ex/jira/{cloudId}/rest/api/3/myself
Example:
maton jira whoami --cloud-id abc-123
GET /jira/ex/jira/{cloudId}/rest/api/3/user/search?query=john
Example:
maton jira user search john --cloud-id abc-123
GET /jira/ex/jira/{cloudId}/rest/api/3/issuetype
Example:
maton jira issuetype list --cloud-id abc-123
GET /jira/ex/jira/{cloudId}/rest/api/3/priority
Example:
maton jira priority list --cloud-id abc-123
GET /jira/ex/jira/{cloudId}/rest/api/3/status
Example:
maton jira status list --cloud-id abc-123
# Discover accessible Jira Cloud resources
maton jira cloud list
# Search issues with JQL
maton jira issue search 'project = PROJ AND status = "In Progress"' --cloud-id abc-123
# Filter with jq
maton jira issue search 'project = PROJ' --cloud-id abc-123 \
--json --jq '.issues | map(select(.fields.status.name == "In Progress"))'
# Create an issue
maton jira issue create --cloud-id abc-123 --project PROJ --summary 'Fix login'
// Get cloud ID first
const resources = await fetch(
'https://api.maton.ai/jira/oauth/token/accessible-resources',
{ headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } }
).then(r => r.json());
const cloudId = resources[0].id;
// Search issues
const issues = await fetch(
`https://api.maton.ai/jira/ex/jira/${cloudId}/rest/api/3/search/jql?jql=project=KEY`,
{ headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } }
).then(r => r.json());
import os
import requests
headers = {'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
# Get cloud ID
resources = requests.get(
'https://api.maton.ai/jira/oauth/token/accessible-resources',
headers=headers
).json()
cloud_id = resources[0]['id']
# Search issues
issues = requests.get(
f'https://api.maton.ai/jira/ex/jira/{cloud_id}/rest/api/3/search/jql',
headers=headers,
params={'jql': 'project=KEY', 'maxResults': 10}
).json()
/oauth/token/accessible-resourcesproject=KEY)curl -g when URLs contain brackets (fields[], sort[], records[]) to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. You may get "Invalid API key" errors when piping.| Status | Meaning |
|---|---|
| 400 | Missing Jira connection or invalid JQL |
| 401 | Invalid or missing Maton API key |
| 429 | Rate limited (10 req/sec per account) |
| 4xx/5xx | Passthrough error from Jira API |
CLI:
maton whoami
maton connection list
Manual:
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
jira. For example:https://api.maton.ai/jira/ex/jira/{cloudId}/rest/api/3/projecthttps://api.maton.ai/ex/jira/{cloudId}/rest/api/3/project