diff --git a/lib/util/http/jira.spec.ts b/lib/util/http/jira.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4163f3b1660af656b0e504c357aa3259422d346f
--- /dev/null
+++ b/lib/util/http/jira.spec.ts
@@ -0,0 +1,27 @@
+import * as httpMock from '../../../test/http-mock';
+import { JiraHttp, setBaseUrl } from './jira';
+
+describe('util/http/jira', () => {
+  const api = new JiraHttp();
+
+  it('throws error if setBaseUrl not called', async () => {
+    await expect(api.postJson('some-path')).rejects.toThrow(
+      new TypeError('Invalid URL')
+    );
+  });
+
+  it('accepts custom baseUrl', async () => {
+    const siteUrl = 'https://some-site.atlassian.com';
+    httpMock.scope(siteUrl).post('/some-path').reply(200, {});
+    setBaseUrl(siteUrl);
+
+    expect(await api.postJson('some-path')).toEqual({
+      authorization: false,
+      body: {},
+      headers: {
+        'content-type': 'application/json',
+      },
+      statusCode: 200,
+    });
+  });
+});
diff --git a/lib/util/http/jira.ts b/lib/util/http/jira.ts
new file mode 100644
index 0000000000000000000000000000000000000000..df51c152a47c08d93844c32cc3ddc95ad1a9f7f0
--- /dev/null
+++ b/lib/util/http/jira.ts
@@ -0,0 +1,22 @@
+import type { HttpOptions, HttpResponse, InternalHttpOptions } from './types';
+import { Http } from '.';
+
+let baseUrl: string;
+
+export const setBaseUrl = (url: string): void => {
+  baseUrl = url;
+};
+
+export class JiraHttp extends Http {
+  constructor(type = 'jira', options?: HttpOptions) {
+    super(type, options);
+  }
+
+  protected override request<T>(
+    url: string | URL,
+    options?: InternalHttpOptions
+  ): Promise<HttpResponse<T>> {
+    const opts = { baseUrl, ...options };
+    return super.request<T>(url, opts);
+  }
+}