Jira is the project management tool that developers love to complain about and organizations refuse to abandon. The platform is genuinely powerful — deep customization, flexible workflows, enterprise-grade permissions — and genuinely frustrating — slow UI, overly complex configuration, and an API that reflects 20 years of accumulated decisions.
Integrating OpenClaw with Jira is worth the effort. Issue triage, sprint planning queries, and standup digests become significantly less painful with an AI layer in front of Jira’s UI. But there are things to know before you start.
API Token Setup: Cloud vs. Server
Jira comes in two flavors with different auth models.
Jira Cloud
Cloud instances live at yourcompany.atlassian.net. Authentication uses an API token plus your email address (not a standalone token like most modern APIs).
Generate an API token:
- Go to id.atlassian.com/manage-profile/security/api-tokens
- Click Create API token
- Name it “OpenClaw”
- Copy the token immediately
The credentials are your Atlassian email and the token, combined as Basic Auth:
# OpenClaw config for Jira Cloud
jira_cloud:
base_url: "https://yourcompany.atlassian.net"
email: "[email protected]"
api_token: "ATATT3xFf..."
All API requests use Basic Auth:
Authorization: Basic base64(email:token)
Jira Server / Data Center
On-premise instances use a different auth path. Jira Server still supports basic auth with username/password, but the recommended approach is Personal Access Tokens (PATs), introduced in Jira 8.14.
Generate a PAT on Jira Server:
- Go to your Jira instance → Profile → Personal Access Tokens
- Create a token with appropriate permissions
- Copy it
# OpenClaw config for Jira Server
jira_server:
base_url: "https://jira.yourcompany.internal"
personal_access_token: "your-PAT-here"
Server PAT auth uses a Bearer token:
Authorization: Bearer your-PAT-here
The version matters: If your Jira Server is older than 8.14, you’re using basic auth with username/password. Check your version at: Administration → System → System Info.
OAuth 2.0 (For Multi-User Setups)
If you’re building a shared OpenClaw setup where multiple team members authenticate with their own Jira credentials, you need OAuth 2.0. This requires registering an application in Atlassian’s developer console and handling the OAuth flow. For personal use, skip OAuth and use API tokens.
Understanding Jira’s REST API
Jira’s API base URL for Cloud: https://yourcompany.atlassian.net/rest/api/3/
Jira Server: https://yourjira.internal/rest/api/2/
Note the version difference. Cloud uses API v3; Server is typically v2. Some field shapes differ between versions — if you’re copying API examples, verify which version applies.
Core endpoints:
GET /rest/api/3/issue/{issueKey} # Get issue
POST /rest/api/3/issue # Create issue
PUT /rest/api/3/issue/{issueKey} # Update issue
GET /rest/api/3/search?jql={jql} # JQL search
POST /rest/api/3/issue/{issueKey}/comment # Add comment
GET /rest/api/3/project/{projectKey} # Get project
GET /rest/api/3/myself # Verify auth
Test your credentials:
@openclaw check jira connection
Internally: GET /rest/api/3/myself — returns your account info if auth is correct.
JQL: The Query Language That Makes Jira Useful
JQL (Jira Query Language) is Jira’s search syntax. Mastering it — or letting OpenClaw translate natural language into JQL — is the key to useful automation.
Natural Language → JQL
@openclaw show me high-priority bugs in the PLATFORM project assigned to me, unresolved, updated in the last 7 days
OpenClaw constructs:
project = PLATFORM
AND issuetype = Bug
AND priority in (High, Highest)
AND assignee = currentUser()
AND resolution = Unresolved
AND updated >= -7d
ORDER BY updated DESC
And queries:
GET /rest/api/3/search?jql=[encoded_jql]&fields=summary,status,priority,assignee,updated&maxResults=50
Common JQL Patterns
Sprint planning:
project = ENG
AND sprint = "Sprint 42"
AND status != Done
ORDER BY priority DESC
Overdue issues:
project = ENG
AND due <= now()
AND status != Done
AND resolution = Unresolved
ORDER BY due ASC
Recently created in triage:
project = ENG
AND status = "Backlog"
AND created >= -24h
ORDER BY created DESC
Blocked issues:
project = ENG
AND labels = blocked
AND status != Done
Issues by epic:
"Epic Link" = ENG-100
Issues without epic (orphaned work):
project = ENG
AND "Epic Link" is EMPTY
AND issuetype != Epic
AND status != Done
JQL Date Functions
Jira’s date functions are powerful for automation:
-7d= 7 days ago-1w= 1 week agostartOfWeek()= start of current weekendOfSprint()= end of current sprintnow()= current time
@openclaw what work was completed in the current sprint so far?
project = ENG
AND sprint in openSprints()
AND status = Done
AND resolutiondate >= startOfWeek()
Sprint Planning Automation
Velocity Analysis
@openclaw what's the Engineering team's average velocity for the last 5 sprints?
OpenClaw queries completed sprints via the Agile API:
GET /rest/agile/1.0/board/{boardId}/sprint?state=closed
Fetches story points completed per sprint and calculates average, trend, and variability.
Sprint Capacity Check
@openclaw is the current sprint overcommitted?
OpenClaw:
- Fetches all issues in the active sprint with story points
- Sums committed points
- Compares against the team’s average velocity
- Flags if committed > velocity × 1.1 (10% buffer threshold)
Backlog Refinement Suggestions
@openclaw suggest backlog issues for the next sprint given our velocity of 45 points
OpenClaw:
- Fetches prioritized, unassigned backlog issues sorted by priority
- Filters for issues with story points estimated
- Suggests a combination that totals near 45 points
- Prioritizes issues by dependency (checks if they block other issues)
Issue Triage Automation
The Triage Problem in Jira
Jira’s “Backlog” state fills up fast. Without regular triage, you end up with hundreds of unestimated, uncategorized issues that nobody looks at. OpenClaw can systematically work through the backlog.
@openclaw triage the last 30 days of new backlog issues in PLATFORM project
For each untriaged issue, OpenClaw:
- Reads title and description
- Classifies issue type (if not set): Bug, Story, Task, Improvement
- Suggests priority based on content keywords
- Adds appropriate labels
- Posts a triage comment explaining the classification
Triage comment template:
? OpenClaw Triage
Type: Bug (detected: "error", "not working")
Suggested priority: High
Labels: backend, payments
Reasoning: Mentions payment processing failure in production environment.
Recommended for: Next sprint or immediate escalation if customer-facing.
Review and adjust as needed.
The comment makes the automation auditable — you can review OpenClaw’s reasoning and override where it’s wrong.
The “Why Jira Webhooks Are Flaky” Workaround
Jira webhooks exist, but they have a reputation for unreliability. Here’s why and what to do about it.
The Problem
Jira Cloud webhooks are generally reliable but have issues:
- Delivery lag: Webhook payloads can be delayed by 30+ seconds during high-traffic periods
- Duplicate delivery: Jira occasionally delivers the same event twice
- No delivery guarantee: Jira doesn’t retry on failure (unlike Stripe, GitHub)
- Missing event types: Some field changes don’t trigger webhooks despite the documentation claiming they do
Jira Server webhooks have all of the above plus:
- Firewall issues: Server instances behind corporate firewalls can’t reach external webhook receivers
- Self-signed certificates: If your webhook receiver uses HTTPS with a self-signed cert, Jira Server rejects it
- No webhook logs: Server gives you no visibility into webhook delivery status
The Workaround: Polling + Idempotent Updates
Instead of relying on webhooks, use a polling approach:
# Poll every 5 minutes for recent changes
last_check = datetime.now() - timedelta(minutes=5)
jql = f'updated >= "{last_check.strftime("%Y-%m-%d %H:%M")}" ORDER BY updated DESC'
This is less elegant than real-time webhooks but more reliable. For most automation use cases (triage, standup digest, sprint planning), a 5-minute polling interval is perfectly adequate.
The idempotency requirement: When polling, you’ll sometimes process the same issue multiple times (if it was updated before your last poll but you process it again). Build automations to be idempotent — check if the action was already performed before doing it again.
For triage: before adding labels, check if labels already exist. Before adding a triage comment, check if one is already present (search comments for your bot’s signature).
# Idempotency check in triage
if "? OpenClaw Triage" in existing_comments:
skip this issue # already triaged
If You Do Use Webhooks
Register webhooks in Jira Cloud: Settings → System → WebHooks → Create a WebHook
Configure only the events you need — each unnecessary event type adds noise and processing load.
Handle duplicates: Store a cache of processed event IDs for 1 hour. If you see the same event ID twice, skip it.
Add a health check: Periodically verify your webhook receiver is getting events by checking the last received timestamp. If it’s been more than 30 minutes with no events, fall back to polling.
PaioClaw’s Jira integration uses polling by default with optional webhook support, handling the deduplication and fallback automatically.
Creating and Updating Issues
Create an Issue
@openclaw create a bug in PLATFORM project: Users getting 500 error on checkout, priority High, label: payments
POST /rest/api/3/issue
{
"fields": {
"project": { "key": "PLATFORM" },
"issuetype": { "name": "Bug" },
"summary": "Users getting 500 error on checkout",
"priority": { "name": "High" },
"labels": ["payments"],
"description": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [{ "type": "text", "text": "Users getting 500 error on checkout" }]
}
]
}
}
}
Note the description format: Jira Cloud API v3 uses Atlassian Document Format (ADF) for rich text — not plain text, not markdown, not HTML. It’s a JSON document tree. OpenClaw handles the conversion from natural language to ADF, but if you write custom skills, account for this.
Jira Server API v2 still accepts plain text or wiki markup in descriptions. Cloud does not.
Transition Issue Status
Changing an issue’s status in Jira isn’t as simple as status = "In Progress". You have to trigger a transition — a workflow step — by its transition ID.
Get available transitions for an issue:
GET /rest/api/3/issue/{issueKey}/transitions
Returns the list of available transitions from the issue’s current state. Each has an ID.
Perform the transition:
POST /rest/api/3/issue/{issueKey}/transitions
{ "transition": { "id": "21" } }
The gotcha: Transition IDs are workflow-specific and different for every Jira instance. There’s no universal “start progress” transition ID. OpenClaw fetches available transitions dynamically and matches your natural language command to the right transition.
@openclaw move PLATFORM-341 to In Progress
OpenClaw gets available transitions → finds one named “In Progress” or “Start Progress” → triggers it.
Standup Digest
@openclaw generate my Jira standup for today
Output:
? Jira Standup — Tuesday, May 19, 2026
✅ COMPLETED YESTERDAY
• PLATFORM-287: Fixed checkout 500 error — resolved, in QA
• ENG-341: Updated API rate limiting docs — done
? IN PROGRESS
• PLATFORM-301: Payment provider migration — blocked on legal review
• ENG-355: Mobile API endpoints — 70% complete
⏳ BLOCKED
• PLATFORM-301: Waiting on legal to review provider contract
? DUE THIS SPRINT
• ENG-371: Database migration (due May 22)
• PLATFORM-310: Security audit findings (due May 24)
Permissions and the Issues They Create
Jira’s permission model is granular. Your API token operates with the same permissions as your Jira account. If your account can’t see a project in the UI, the API returns 403 or simply excludes those issues from search results.
Common permission issues:
- Issues from restricted projects don’t appear in JQL search results (no error, just missing data)
- Creating issues in a project requires “Create Issues” project permission
- Transitioning issues may require specific workflow permissions
- Some custom fields are only visible to certain groups
If OpenClaw’s queries are returning fewer results than expected, check your Jira permissions for the relevant projects.
Performance Considerations
Jira’s API can be slow, especially on Cloud during peak hours and on Server with large datasets.
Pagination is mandatory: JQL search returns a maximum of 100 results per request. For queries returning more, paginate with startAt and maxResults:
GET /rest/api/3/search?jql=...&startAt=0&maxResults=100
GET /rest/api/3/search?jql=...&startAt=100&maxResults=100
Use fields parameter: Fetching all fields is slow. Specify only what you need:
GET /rest/api/3/search?jql=...&fields=summary,status,priority,assignee
Rate limits: Jira Cloud has rate limits (undocumented but approximately 10 requests/second). Server limits depend on your instance configuration. Add delays between bulk operations.
PaioClaw vs. Self-Hosted
Self-hosting the Jira integration works well for personal use on Cloud. Where complexity grows:
Server/Data Center behind VPNs: API calls from an external server fail if your Jira instance isn’t publicly accessible. You’d need OpenClaw running inside the network. PaioClaw supports on-premise agents that run inside your network and relay to PaioClaw’s cloud layer.
Atlassian Document Format: Writing back to Jira with rich formatting requires ADF. Building ADF serialization into custom skills is annoying work that PaioClaw handles for you.
Webhook reliability: As described above, Jira webhooks are unreliable enough that you need a robust fallback. PaioClaw’s polling + webhook hybrid approach is battle-tested.
Plans start free, Smart at $15/mo, Genius at $25/mo.
Summary
Jira’s integration complexity is real but manageable. The key points: Cloud uses email+API token with Basic Auth, Server uses PAT with Bearer; the description field on Cloud requires Atlassian Document Format (not plain text); status transitions require fetching available transitions dynamically rather than assuming IDs; and webhooks are unreliable enough that polling should be your primary data retrieval strategy.
The automation that delivers the most value fastest is JQL-powered querying via natural language — removing the friction of remembering Jira’s query syntax makes the tool significantly more useful in daily work. Standup digest and sprint velocity reporting are the next most valuable automations, and both are straightforward to set up once the JQL integration is working.

