ScriptRunner HAPI: The Scripting Revolution That Changes Everything

ScriptRunner HAPI: The Scripting Revolution That Changes Everything

Sponsored by Adaptavist

My reaction when I first saw HAPI:

"Are you saying the left side equals the right side?"

"Yes, identical behavior."

"No, you're shi**ing me."

That was my genuine reaction. I still smile thinking about it.

After 14+ years as a Jira consultant, I've struggled with ScriptRunner like everyone else. Groovy syntax was powerful but brutal. The learning curve kept admins away. Copy-paste scripts rarely worked.

HAPI changes everything.

Let me show you why this is the biggest update to ScriptRunner in years—and why you need to start using it today.


What Is HAPI? (Simple Answer)

HAPI = Human API

It's ScriptRunner for Jira, redesigned to be actually usable by humans.

Before HAPI:

// Old way - ~20 lines just to create a ticket
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueFactory
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.IssueManager

def issueFactory = ComponentAccessor.getIssueFactory()
def issueManager = ComponentAccessor.getIssueManager()
def constantsManager = ComponentAccessor.getConstantsManager()

MutableIssue issue = issueFactory.getIssue()
issue.setProjectObject(projectManager.getProjectByCurrentKey("DS"))
issue.setIssueType(constantsManager.getAllIssueTypeObjects().find { it.name == "Task" })
issue.setSummary("My ticket")
// ... 10 more lines ...

With HAPI:

// New way - 3 lines
Issues.create('DS', 'Task') {
    setSummary('My ticket')
}

Same result. 70% less code.

That's not hyperbole. That's actual code reduction.


Why HAPI Is a Game-Changer

Problem #1 (Before HAPI): Groovy Was Intimidating

The old ScriptRunner experience:

  1. Admin needs to automate something
  2. Opens ScriptRunner Console
  3. Blank screen stares back
  4. Googles "how to create Jira issue groovy"
  5. Finds 5-year-old forum post
  6. Copy-pastes code
  7. Error: Class not found
  8. Gives up
  9. Manually clicks through Jira forever

Sound familiar?

This was my reality for YEARS. I'm a certified Atlassian consultant and even I struggled.

Solution (With HAPI): Intuitive, Readable, Human

The new HAPI experience:

  1. Admin needs to automate something
  2. Opens ScriptRunner Console
  3. Types: Issues.
  4. Auto-complete appears with every possible action
  5. Selects create()
  6. Types: Issues.create(
  7. Auto-complete shows: project key, issue type
  8. Fills in: 'DS', 'Task'
  9. Types: { and hits Enter
  10. Auto-complete shows: setSummary, setDescription, setPriority, etc.
  11. Script writes itself
  12. It works

This is how it should have always been.

Problem #2 (Before HAPI): No IDE Support

Old console:

  • No syntax highlighting
  • No auto-completion
  • No error detection
  • Code blind

My workaround: Use IntelliJ IDEA, configure Groovy SDK, connect to Jira instance, pray.

Total setup time: 2-3 hours. Success rate: 60%.

Solution (With HAPI): Built-in IDE Features

New console:

  • ✅ Full syntax highlighting
  • ✅ Intelligent auto-completion
  • ✅ Inline documentation
  • ✅ Error detection
  • ✅ Copy-paste ready snippets

Setup time: 0 seconds. Already there.

Problem #3 (Before HAPI): Custom Fields Were Hell

Old way to set custom field value:

import com.atlassian.jira.component.ComponentAccessor

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def issueManager = ComponentAccessor.getIssueManager()

def issue = issueManager.getIssueObject("DS-123")
def customField = customFieldManager.getCustomFieldObject(10047) // What is 10047?!

def optionsManager = ComponentAccessor.getOptionsManager()
def config = customField.getRelevantConfig(issue)
def options = optionsManager.getOptions(config)
def option = options.find { it.value == "Mac" }

issue.setCustomFieldValue(customField, option)
issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)

I'm not exaggerating. That's real code to set a dropdown field.

HAPI way:

Issues.get('DS-123').update {
    setCustomFieldValue('Mac or PC', 'Mac')
}

ONE LINE.

No field IDs. No option managers. No ceremony. Just set the value.


HAPI in Action: Real Examples

Let me show you what you can actually do.

Example 1: Create a Basic Task

Scenario: Need to create a task in project "DS"

Issues.create('DS', 'Task') {
    setSummary('Review Q4 budget')
}

Result: Task created. Done.

What you get:

  • Auto-assigns to default assignee
  • Sets default priority
  • Uses project's default workflow
  • Ready to use

Example 2: Create Task with Details

Scenario: Task with priority, labels, assignee, due date

Issues.create('DS', 'Task') {
    setSummary('Update documentation')
    setDescription('Refresh onboarding docs for new process')
    setPriority('High')
    setAssignee('mike.smith')
    setLabels('documentation', 'onboarding')
    setDueDate('2026-02-15')
}

Before HAPI: 25+ lines of imports and boilerplate With HAPI: 8 readable lines

Example 3: Create Story with Custom Fields

Scenario: User story with custom fields for equipment

Issues.create('DS', 'Story') {
    setSummary('New employee onboarding - John Smith')
    setDescription('Onboard new developer starting Feb 1')
    setPriority('High')
    setAssignee('hr.admin')
    setLabels('onboarding', 'new-hire')
    setDueDate('2026-02-01')
    setCustomFieldValue('Mac or PC', 'Mac')
    setCustomFieldValue('Monitor Needed', 'Yes')
    setCustomFieldValue('Department', 'Engineering')
}

Custom fields work like native fields. No IDs. No lookups. Just names.

Example 4: Update an Existing Issue

Scenario: Change priority and add comment to DS-37

Issues.get('DS-37').update {
    setPriority('Critical')
    appendDescription('\n\nUpdate: Issue escalated to P1')
    addComment('Escalated due to customer impact')
}

Notice: appendDescription (adds to existing) vs setDescription (replaces)

HAPI is smart about these details.

Example 5: Bulk Update from JQL

Scenario: Update all open high-priority tasks

Issues.search('project = DS AND priority = High AND status = Open').each { issue ->
    issue.update {
        setAssignee('senior.admin')
        addComment('Reassigned for urgent handling')
    }
}

Old way: Would require complex issue manager loops, null checks, etc. HAPI way: Reads like English.

Example 6: Create Project (Yes, Really)

Scenario: New Scrum project for demo purposes

Projects.create('DPS', 'Demo Project Scrum') {
    projectLead = 'admin'
    projectType = 'Scrum'
    description = 'Test project for HAPI examples'
    url = 'https://projectflow.co.uk'
    setDefaultAssigneeToProjectLead()
    avatarId = 10001
}

Creating projects via script used to be nightmare territory.

With HAPI: 8 lines. Actually readable.

Example 7: Add Watchers

Scenario: Add team members as watchers to critical ticket

Issues.get('DS-42').update {
    addWatcher('mike.consultant')
    addWatcher('sarah.manager')
    addWatcher('john.developer')
}

Example 8: Set Custom Field with Multiple Values

Scenario: Multi-select custom field for software licenses

Issues.get('DS-55').update {
    setCustomFieldValue('Software Needed', ['Office 365', 'Salesforce', 'Slack'])
}

Multi-select fields just work. Pass an array. Done.

Example 9: Clone Issue with Modifications

Scenario: Copy ticket but change assignee and priority

def original = Issues.get('DS-100')

Issues.create('DS', original.issueType.name) {
    setSummary(original.summary + ' (Copy)')
    setDescription(original.description)
    setPriority('Medium') // Change from original
    setAssignee('new.assignee') // Different assignee
}

Example 10: Advanced - Conditional Logic

Scenario: Update ticket based on custom field value

def issue = Issues.get('DS-88')

issue.update {
    if (issue.getCustomFieldValue('Equipment Type') == 'Laptop') {
        setCustomFieldValue('Mac or PC', 'Mac')
        setCustomFieldValue('RAM', '16GB')
    } else {
        setCustomFieldValue('Mac or PC', 'PC')
        setCustomFieldValue('RAM', '8GB')
    }
}

HAPI doesn't limit you. Full Groovy power still available.


The Auto-Complete Revolution

This deserves its own section because it's THAT good.

How Auto-Complete Works

Type: Issues.

Auto-complete shows:

  • create()
  • get()
  • search()
  • getByKey()

Type: Issues.create(

Auto-complete shows:

Issues.create(projectKey: String, issueType: String)

Tells you exactly what parameters it needs.

Type: Issues.create('DS', 'Task') {

Auto-complete shows:

  • setSummary()
  • setDescription()
  • setPriority()
  • setAssignee()
  • setLabels()
  • setDueDate()
  • setCustomFieldValue()
  • ... everything you can set

Type: setPriority(

Auto-complete shows:

  • 'Highest'
  • 'High'
  • 'Medium'
  • 'Low'
  • 'Lowest'

IT KNOWS YOUR PRIORITIES. It's pulling from your Jira instance.

Type: setCustomFieldValue(

Auto-complete shows all your custom fields by NAME:

  • 'Mac or PC'
  • 'Department'
  • 'Equipment Type'
  • 'Start Date'

NO MORE FIELD IDs. This alone is worth the upgrade.


Script Snippets Library (Even Easier)

Don't want to write code at all?

HAPI includes pre-built snippets.

How to Use Snippets

  1. Open ScriptRunner Console
  2. Click Snippets button
  3. Browse library:
    • Add Comment
    • Update Custom Field
    • Create Issue
    • Bulk Update
    • And more...
  4. Click snippet
  5. Code appears in console
  6. Adjust parameters
  7. Run

Example: Add Comment Snippet

Click "Add Comment" snippet, get:

Issues.get('PROJECT-123').update {
    addComment('Your comment here')
}

Change PROJECT-123 to your issue key. Change comment text. Done.

This is training wheels for HAPI. Use snippets to learn syntax, then write your own.


Migration: Your Old Scripts Still Work

Critical point: You DON'T need to rewrite everything.

100% Backward Compatible

Old Groovy scripts:

  • ✅ Still work
  • ✅ No breaking changes
  • ✅ Run alongside HAPI scripts

You can migrate gradually:

  • Use HAPI for new scripts
  • Keep old scripts as-is
  • Update old scripts when you touch them (optional)

Hybrid Mode (My Favorite Feature)

You can MIX old and new syntax in the same script.

Example:

// Old Groovy style
import com.atlassian.jira.component.ComponentAccessor
def userManager = ComponentAccessor.getUserManager()
def user = userManager.getUserByName('admin')

// HAPI style in same script
Issues.create('DS', 'Task') {
    setSummary('Hybrid script example')
    setAssignee(user.name) // Using variable from old-style code
}

This works. Old and new code cooperate.

Why this matters: Migrate at your own pace. No pressure. No rush.


Real Client Success Story

Company: Mid-size insurance firm, 500 employees Challenge: Onboarding process required 15 Jira tickets per new employee Old solution: Manual creation (30 minutes per employee)

HAPI solution:

def createOnboardingTickets(employeeName, startDate, department) {
    
    // Ticket 1: IT Equipment
    Issues.create('HR', 'Task') {
        setSummary("Equipment for ${employeeName}")
        setDescription("Laptop, monitor, phone needed by ${startDate}")
        setPriority('High')
        setAssignee('it.procurement')
        setDueDate(startDate)
        setCustomFieldValue('Department', department)
        setCustomFieldValue('Equipment Type', 'Full Setup')
    }
    
    // Ticket 2: System Access
    Issues.create('IT', 'Task') {
        setSummary("Access for ${employeeName}")
        setDescription("Email, VPN, software licenses")
        setPriority('High')
        setAssignee('it.admin')
        setDueDate(startDate)
        setCustomFieldValue('Department', department)
    }
    
    // Ticket 3: Workspace Setup
    Issues.create('FAC', 'Task') {
        setSummary("Workspace for ${employeeName}")
        setDescription("Desk, chair, supplies")
        setPriority('Medium')
        setAssignee('facilities')
        setDueDate(startDate)
        setCustomFieldValue('Floor', department == 'Engineering' ? '3' : '2')
    }
    
    // ... 12 more tickets
}

// Run for new employee
createOnboardingTickets('John Smith', '2026-02-15', 'Engineering')

Result:

  • 15 tickets created in < 1 second
  • Consistent formatting
  • No manual errors
  • HR loves it

Time saved: 30 minutes → 30 seconds per employee

ROI: Paid for ScriptRunner license in first month.


Who Should Use HAPI?

Perfect For:

New ScriptRunner Users:

  • Learn scripting without Groovy expertise
  • Auto-complete teaches you as you go
  • Snippets provide examples

Experienced Admins:

  • Write scripts 70% faster
  • Less boilerplate
  • More readable code

Consultants (Like Me):

  • Faster implementations
  • Easier to hand off to clients
  • Less debugging

Teams:

  • Code reviews easier (readable syntax)
  • Knowledge sharing simpler
  • Onboarding faster

Not For:

Jira Cloud users (HAPI is Data Center/Server only)

That's it. Everyone else should use this.


How to Get Started (Right Now)

Step 1: Update ScriptRunner

Already have ScriptRunner?

  1. Admin → Manage Apps
  2. Find ScriptRunner for Jira
  3. Click Update (if available)
  4. Wait 30 seconds
  5. HAPI is now active

No extra cost. No new license. Already included.

Step 2: Open Console

  1. ScriptRunner → Console
  2. Notice new interface
  3. Auto-complete ready to go

Step 3: Try First Script

Copy this:

Issues.create('YOUR-PROJECT', 'Task') {
    setSummary('My first HAPI script')
}

Replace YOUR-PROJECT with actual project key

Click Run

Check your project. Ticket created.

Congratulations. You're now a ScriptRunner HAPI user.

Step 4: Explore Snippets

  1. Click Snippets button
  2. Browse examples
  3. Click one
  4. Adjust parameters
  5. Run

Learn by doing.

Step 5: Read Documentation

Adaptavist docs are excellent:


Common Questions

Q: Does HAPI work with ScriptRunner for Confluence?

A: Not yet. HAPI is currently Jira-only. But I expect it'll come to Confluence eventually.

Q: Can I use HAPI in post-functions?

A: Yes! Any HAPI script in console can be used in:

  • Post-functions
  • Validators
  • Conditions
  • Scheduled jobs
  • Listeners

Just copy-paste from console to post-function. Works identically.

Q: What about performance?

A: HAPI is actually FASTER than old Groovy in many cases. Adaptavist optimized under the hood.

I tested: Creating 100 issues

  • Old Groovy: 8.5 seconds
  • HAPI: 6.2 seconds

HAPI is faster AND easier.

Q: Do I need to learn Groovy?

A: Not really. HAPI abstracts most complexity.

You'll pick up basics through auto-complete and snippets.

For advanced stuff: Yes, Groovy knowledge helps. But 90% of use cases don't need it.

Q: What if auto-complete doesn't show my custom field?

A: Refresh console (F5). HAPI caches custom fields. Refresh pulls latest.

Or: Use field ID if you must: setCustomFieldValue(10047, 'value')

(But names work 99% of the time)

Q: Can I get help?

A: Yes:

  • Adaptavist Community: https://community.adaptavist.com/
  • Documentation: https://docs.adaptavist.com/
  • Comment on my video: https://youtu.be/PcPtG5tCdFM

The Bottom Line

HAPI is the biggest improvement to ScriptRunner in years.

Before HAPI:

  • Groovy was intimidating
  • Copy-paste rarely worked
  • Learning curve was brutal
  • Many admins avoided scripting entirely

After HAPI:

  • Auto-complete writes code for you
  • Scripts are readable
  • Custom fields work by name
  • Anyone can learn it

If you're on Jira Data Center/Server and have ScriptRunner:

Update today. Start using HAPI.

If you don't have ScriptRunner yet:

This is your sign to get it.


Free Resources

My HAPI Script Library (GitHub): http://bit.ly/3mDylJg

  • 20+ real-world examples
  • Onboarding automation
  • Bulk update scripts
  • Custom field helpers
  • All free to copy

Watch My HAPI Tutorial (YouTube): https://youtu.be/PcPtG5tCdFM

  • 15-minute walkthrough
  • Live coding examples
  • Mistakes and fixes
  • Real console demo

Try HAPI (Adaptavist): https://bit.ly/scriptrunnerhapiw

  • Official documentation
  • Interactive examples
  • API reference

Adaptavist Documentation: https://docs.adaptavist.com/sr4js/latest/features/hapi


Special Thanks

Big thank you to Adaptavist for sponsoring this article and, more importantly, for building HAPI.

This isn't just a feature update. It's a fundamental rethinking of how admins should interact with Jira automation.

You've made scripting accessible. That's huge.


Questions about HAPI or ScriptRunner? Join my Skool community where I answer Jira questions regularly.

Need help implementing ScriptRunner for your organization? I do ScriptRunner consulting and training. Book a consultation.


💡
Disclosure: This article is sponsored by Adaptavist. All opinions, enthusiasm, and "this is amazing" reactions are genuinely mine. I wouldn't recommend something I don't actually use and love.