ml-connector
QADJira

QAD and Jira integration

QAD runs manufacturing, procurement, and finance. Jira runs the issue tracking and project work that surrounds those processes. Connecting the two lets QAD events such as a held supplier invoice, a failed three-way match, or a late goods receipt show up as Jira issues that operations and approvers can follow, while the resolution and custom fields people set on those issues feed status back to QAD. Jira has no native invoice, purchase order, payment, or GL objects, so the financial detail rides in custom fields the customer configures, and ml-connector maps those fields to QAD on a schedule you control.

How QAD works

QAD Adaptive ERP exposes suppliers, purchase orders, supplier invoices, GL accounts, cost centers, items, goods receipts, and AP payments through REST business document APIs, documented in Swagger inside each customer instance. The cloud product authenticates with a JWT session or OAuth2 bearer token against a tenant-specific URL, so there is no shared hostname, public sandbox, or developer portal. Older on-premise sites run QAD Enterprise Edition with the QXtend SOAP framework instead. QAD cloud has no native webhook system for connectors, so records are read by polling on a schedule.

How Jira works

Jira Cloud exposes issues, projects, users, comments, worklogs, and custom fields through its REST API v3, reached at api.atlassian.com for OAuth or the customer subdomain at atlassian.net for API tokens. It authenticates with OAuth 2.0 authorization code (3LO) or with an email and API token over basic auth; client-credentials OAuth is not supported. It has no native finance objects, so PO numbers, supplier names, and cost codes are carried in customer-defined custom fields on issues. Jira supports real push webhooks, signed with HMAC-SHA256 in the X-Hub-Signature header, and uses offset and cursor-based pagination under per-tenant rate limits.

What moves between them

The main flow runs from QAD into Jira. ml-connector reads QAD purchase orders, supplier invoices, and goods receipts and creates or updates Jira issues, writing PO numbers, suppliers, and amounts into the matching custom fields and the issue summary and description. The return flow runs from Jira into QAD: when an issue is transitioned to done or its approval and cost-code custom fields change, ml-connector reads those values and updates the related QAD record. QAD is polled on a schedule because it has no push, while Jira issue changes arrive over webhooks within seconds. User records are read from Jira by accountId for assignee mapping but never written, since Atlassian manages users through admin rather than the Jira API.

How ml-connector handles it

ml-connector stores both credential sets encrypted and sends the Jira OAuth bearer token or basic API token on every call, refreshing the rotating OAuth refresh token when a request returns 401. After OAuth it calls accessible-resources to resolve the customer cloudId and stores it alongside the tokens, since the API URL cannot be built without it. On the QAD side it accepts the full tenant URL per customer, since QAD publishes no shared base address, and validates entity paths against that instance. Because QAD cloud is pull-only, it polls purchase orders, invoices, and receipts on a schedule, while it registers a Jira webhook scoped by JQL and verifies the HMAC-SHA256 signature on each incoming event. Custom fields are mapped by field id rather than name, discovered through the field endpoint at connect time, since ids differ per instance and names can be renamed, and issue descriptions are written in Atlassian Document Format rather than plain text. Jira has no idempotency key for issue creation, so the connector writes the QAD record id into a custom field and JQL-searches it before creating to avoid duplicates, backed by a BullMQ jobId on the queue. Jira rate limits return 429 with a Retry-After header, so ml-connector backs off and retries, and because REST-registered webhooks expire after 30 days it refreshes them before they lapse. Every record carries a full audit trail and can be replayed if a downstream call fails.

A real-world example

A mid-sized discrete manufacturer with about 350 employees runs QAD Adaptive ERP for procurement and finance, but its operations and engineering teams work in Jira and have no QAD logins. Before the integration, when a supplier invoice failed the three-way match or a receipt was missing, an AP clerk emailed the buyer and opened a Jira ticket by hand so the issue could be tracked, and the resolution recorded in Jira never made it back to the ERP. With QAD and Jira connected, each matching exception in QAD opens a Jira issue carrying the PO number, supplier, and variance in custom fields, and when the buyer transitions the issue to done the resolution flows back to QAD. The manual ticket creation is gone and both teams see the same state.

What you can do

  • Create and update Jira issues from QAD purchase order, supplier invoice, and receipt exceptions.
  • Carry QAD PO numbers, suppliers, and cost codes in Jira custom fields mapped by field id.
  • Read resolution status and transitions from Jira issues back into the related QAD records.
  • Authenticate Jira with OAuth 2.0 (3LO) or an API token and QAD with its tenant-specific login, resolving cloudId at connect time.
  • Receive Jira issue changes over signed webhooks while polling QAD on a schedule, with retries and a full audit trail.

Questions

Can Jira hold QAD invoices, POs, or GL accounts directly?
No. Jira is an issue and project tracking tool with no native invoice, purchase order, payment, or GL account objects. ml-connector carries that financial detail in Jira custom fields the customer configures, mapping PO numbers, suppliers, and cost codes onto issues. The authoritative finance records stay in QAD.
Which direction does data move between QAD and Jira?
The main flow is QAD into Jira, creating issues from purchase order, invoice, and receipt exceptions. The return flow reads issue transitions, resolution, and cost-code custom fields from Jira back into the matching QAD records. User records are read from Jira by accountId for assignee mapping but never written, since Atlassian manages users outside the Jira API.
How does the integration handle updates given QAD has no webhooks?
Jira supports push webhooks, so ml-connector registers one scoped by JQL and verifies the HMAC-SHA256 signature in the X-Hub-Signature header on each event to pick up issue changes within seconds. QAD cloud has no push, so ml-connector polls purchase orders, invoices, and receipts on a schedule you set. Because REST-registered Jira webhooks expire after 30 days, the connector refreshes them before they lapse.

Related integrations

Connect QAD and Jira

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started