Jira Integration
Keep Jira (or Jira Service Management) as your system of record. AscendCore becomes the approval-gated system of action on top: issues flow in, a human approves in Slack or Teams, the runbook executes, and the decision is written back to the issue as a comment. No migration.
In one sentence
A Jira Automation rule POSTs new issues to AscendCore, where the issue is AI-classified into a runbook, held for explicit human approval, executed against your identity stack, and the outcome lands back on the originating issue as a comment with an audit-chain reference.
How an issue flows
- Ingest. Your Automation rule POSTs the issue to
POST /api/v1/tickets/ingestwith a scoped API key. One issue is ingested at most once: retries and rule re-fires return the original run instead of posting a second card. - Classify. AscendCore classifies the issue text into a runbook intent with a confidence score. Low-confidence or unrecognized issues are received, audit-logged, and left alone (
no_action). Nothing executes on a guess. - Approve.The matching runbook's approval card is posted to your IT admin channel (Slack, or Teams for Teams-channel orgs), with a threaded note showing the originating issue key, a link back to it, and the AI's classification and confidence. A human approves or denies. Every runbook is approval-gated. There is no autonomous path.
- Execute.On approval, the runbook runs against your stack (Okta, Entra ID, M365) and the action is recorded on the org's tamper-evident SHA-256 audit chain.
- Write back. The decision (approved or denied, by whom, at what time) is appended to the originating issue as a comment. Your ITSM keeps the complete story.
Step 1: Create a scoped API key
In your admin portal under API, create a key with the ticket:ingest scope. Least privilege applies: a key with only this scope can submit tickets but cannot execute runbooks directly, read audit rows, or browse the catalog.
You will paste this key into the Automation rule's web-request headers in the next step. It is stored inside the rule, visible only to Jira admins who can edit automation.
Step 2: Add the Automation rule
In Project settings โ Automation (or global automation for multiple projects), create a rule:
- When: Issue created. Add a condition (for example, request type or label) if you only want a subset of issues routed to AscendCore.
- Then: Send web request, with:
- URL:
https://ascendcore.ai/api/v1/tickets/ingest - Method: POST
- Headers:
Authorization: Bearer ak_live_...(mark it hidden) andContent-Type: application/json - Web request body: Custom data, below
- URL:
{
"source": "jira",
"ticket": {
"issueKey": "{{issue.key}}",
"summary": "{{issue.summary.jsonEncode}}",
"description": "{{issue.description.jsonEncode}}",
"url": "{{issue.url}}",
"reporterEmail": "{{issue.reporter.emailAddress}}"
}
}The jsonEncodesmart-value function escapes quotes and newlines in user-entered text so the JSON stays valid. Use the rule's Validate button against a test issue to confirm a 200 before turning it on. Works on Jira Cloud; on Jira Server or Data Center, any webhook or script that POSTs the same payload works identically.
Payload reference
| Field | Required | Purpose |
|---|---|---|
source | Yes | Must be "jira" for this integration. |
ticket.issueKey | Yes | Issue key (ITSM-123). Idempotency key, write-back target, and the number shown to the approver. |
ticket.summary | Yes | Primary classification input. |
ticket.description | No | Appended to the classification input when present. |
ticket.url | No | Deep link back to the issue, shown in the approval thread. |
ticket.reporterEmail | No | Target-user fallback when the issue text names nobody else. May be empty if the reporter's email is hidden by profile privacy settings; the integration tolerates that. |
Supported intents in this release
| Intent | Runbook | System |
|---|---|---|
| MFA reset | RB-002 | Okta |
| Password reset | RB-001 | Okta |
| Offboarding (suspend account) | RB-011 | Okta |
| Account unlock | RB-007 | Microsoft Entra ID |
| M365 license assignment | RB-006 | M365 |
| Group add / remove (group named in the issue) | RB-013 | Microsoft Entra ID |
| New hire provisioning (name and email in the issue) | RB-003 | Okta + M365 |
Issues that classify to anything else are acknowledged with no_action and audit-logged. Additional intents arrive as additive extensions; your Automation rule does not change.
What the write-back looks like
When the approval reaches a decision (from Slack, Teams, or the dashboard), AscendCore posts a comment on the originating issue:
[AscendCore] Runbook decision: APPROVED
Runbook: MFA Reset
Target user: Sarah Chen (sarah.chen@acme.com)
Decision by: slack:U0123APPROVER at 2026-06-09T17:42:11.310Z
Action executed by AscendCore after explicit human approval.
This decision is recorded on the org's tamper-evident audit chain in AscendCore.Denied requests get a comment too, stating that no changes were made. The comment is posted by a Jira service account you provision during onboarding (an API token with comment permission on the relevant projects; least privilege applies). The write-back is deliberately non-blocking: if your site is unreachable, the approval flow itself is unaffected and the decision remains on the AscendCore audit chain.
Security model
- Scoped bearer auth.The integration reuses AscendCore's standard API-key model. Keys are salted-hashed at rest, scope-gated, rate-limited, and revocable from the dashboard.
- Approval-gated, always. Ingested issues follow the same human-in-the-loop policy as every other trigger. AI classifies; it never executes.
- Audit-chained.Every ingestion (including no-action dispositions) and every decision is recorded on the org's tamper-evident SHA-256 audit chain, usable as evidence for SOC 2 and ISO 27001 reviews.
- Idempotent. Duplicate submissions of the same issue return the original run. Retry storms cannot flood your approval channel.
- Sandbox-aware. If your org is in Sandbox Mode, ingested issues exercise the full approval flow with mocked execution and no real write-back.
Full API reference
The complete request/response contract for POST /api/v1/tickets/ingest (dispositions, error codes, schemas) lives in the OpenAPI reference. Using ServiceNow instead? See the ServiceNow guide.
