Load Jira data to Microsoft SQL Server
Build a Jira to Microsoft SQL Server pipeline with your coding agent. One prompt scaffolds it with the dltHub AI harness, plus the Jira API base URL, auth, endpoints, and incremental loading.
Jira Cloud is a project and issue-tracking service whose REST API provides programmatic access to Jira Cloud platform resources. Everything needed to build a working Jira → Microsoft SQL Server pipeline is on this page: the API's base URL, authentication, endpoints, pagination and incremental field — plus a prompt that hands the whole job to your coding agent.
Build your Jira to Microsoft SQL Server pipeline
Paste this prompt into Claude, Codex, or Cursor. The agent does the rest.
uvx dlthub-init@latest to build a pipeline from Jira to Microsoft SQL Server and run it on dltHubThat scaffolds a dltHub workspace and installs the dltHub AI harness — the project rules, the secrets-management skill, and the dlt MCP server your agent needs to work safely. From there it reads the Jira API, proposes the endpoints to load, then writes, runs and validates the pipeline while you review rather than type. Credentials are inspected through MCP tools, so your agent never reads secrets.toml itself. How the LLM-native workflow works →
Prefer to write it yourself? Every fact the agent uses is below.
Jira API at a glance
| Base URL | https://<your-domain>.atlassian.net |
| Example endpoint | GET rest/api/3/search/jql |
| Records found at | issues |
| Authentication | HTTP Basic auth using Atlassian account email plus API token — sent in the Authorization header, prefixed Basic |
| Pagination | Cursor-based via nextPageToken, next cursor at nextPageToken, page size via maxResults (default 50, max 10000). For Jira Cloud REST API v3 issue retrieval using the current enhanced JQL search endpoint (/rest/api/3/search/jql), pagination uses nextPageToken rather than the deprecated startAt. Send nextPageToken from the response in the next request; the response contains nextPageToken and isLast. The page-size parameter is maxResults. Jira's general pagination documentation says endpoint limits vary and can change; callers should inspect the returned maxResults, so there is no universal verified maximum for all v3 list endpoints. For generic paginated endpoints, the documented offset parameters are startAt and maxResults, with response metadata such as startAt, maxResults, total, and isLast. Basic authentication is email plus API token, but it does not affect pagination. |
| Incremental field | updated |
| Record id | id |
| API reference | https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/ |
These values come from the Jira API reference — the authoritative source if anything here looks out of date.
How do I authenticate with the Jira API?
Send HTTP Basic authentication on every request. Construct the credential value from the Atlassian account email, a colon, and the API token, then Base64-encode that string and send Authorization: Basic <base64(email
)>. Send Accept: application/json; for requests with a JSON body, send Content-Type: application/json. The standard site URL form is https://.atlassian.net/rest/api/3/....1. Get your credentials
- Create or use an Atlassian account that has Jira Cloud product access and permission to the projects/data you will read.
- Open https://id.atlassian.com/manage-profile/security/api-tokens and sign in.
- Select Create API token, enter a descriptive name, choose an expiration (Atlassian states the default is one year and the selectable range is 1–365 days), and create the token.
- Copy the token immediately and store it in a secrets manager; Atlassian does not use the account password for this REST authentication flow.
- Configure the connector with the Atlassian account email as the username and the copied API token as the password. Jira Cloud basic-auth requests use an Authorization header containing Base64(email), or an HTTP client's equivalent basic-auth option.
- Use the tenant site as the single base URL: https://your-domain.atlassian.net/rest/api/3. For example, call /myself or /search/jql to validate credentials and permissions.
- If using a service-account scoped token rather than a normal user token, follow the separate service-account credential flow and use the Atlassian API gateway URL with the cloud ID; the simple atlassian.net base URL is for the standard email plus API-token flow.
2. Add them to .dlt/secrets.toml
[sources.jira_source] email = "your-atlassian-account-email@example.com" api_token = "your_jira_cloud_api_token" base_url = "https://your-domain.atlassian.net/rest/api/3"
dlt reads this file automatically at runtime. With the harness, the setup-secrets skill prompts you for the values and never handles the raw credential in chat. For production, see setting up credentials with dlt.
What Jira data can I load into Microsoft SQL Server?
These are the Jira endpoints dlt can load into Microsoft SQL Server:
| Resource | Endpoint | Method | Data selector | Description |
|---|---|---|---|---|
| issues | rest/api/3/search/jql | GET | issues | Enhanced JQL issue search; use JQL such as updated >= "2026-10-11 00" ORDER BY updated ASC; paginate with nextPageToken and maxResults. |
| issues | rest/api/3/search/jql | POST | issues | Enhanced JQL issue search for longer queries; request body supports jql, fields, maxResults, and nextPageToken. |
| issue | rest/api/3/issue/{issueIdOrKey} | GET | Retrieve one issue, including its fields.updated value. | |
| issue_changelog | rest/api/3/issue/{issueIdOrKey}/changelog | GET | values | Paginated changelog for an issue. |
| projects | rest/api/3/project/search | GET | values | Paginated project list; documented response includes values, startAt, maxResults, total, isLast, and nextPage. |
| users | rest/api/3/users | GET | values | User collection endpoint; the user API documents paginated responses using values, startAt, maxResults, and isLast/total where applicable. |
| fields | rest/api/3/field/search | GET | values | Paginated field search; supports filtering fields by ID and query. |
| field_configurations | rest/api/3/fieldconfiguration | GET | values | Paginated list of field configurations. |
| issue_picker | rest/api/3/issue/picker | GET | Issue-picker search response; not a general incremental resource. | |
| issue_bulk_changelog | rest/api/3/changelog/bulkfetch | POST | Bulk-fetch changelogs for multiple issues; query operation rather than a simple list GET. |
How do I load only new Jira records?
Jira exposes updated on rest/api/3/search/jql, so dlt can request only the records that changed since the last run. Set it as the cursor_path and dlt tracks the high-water mark for you between runs.
{"name": "issues", "endpoint": { "path": "rest/api/3/search/jql", "data_selector": "issues", "incremental": {"cursor_path": "updated", "initial_value": "2024-01-01T00:00:00Z"}, }}
On the first run dlt loads everything from initial_value; on every run after that it requests only what changed and appends with write_disposition="merge" if you set a primary key. See incremental loading.
What does the generated Jira pipeline look like?
A standard dlt REST API pipeline — the same code you would write by hand, loading issue search (/search/jql) and issue (/issue/{issueIdOrKey}) from the Jira API into Microsoft SQL Server:
import dlt from dlt.sources.rest_api import RESTAPIConfig, rest_api_resources @dlt.source def jira_source(api_token=dlt.secrets.value): config: RESTAPIConfig = { "client": { "base_url": "https://<your-domain>.atlassian.net", "auth": {"type": "http_basic", "username": "REPLACE_ME", "password": api_token}, }, "resources": [ {"name": "issues", "endpoint": {"path": "rest/api/3/search/jql", "data_selector": "issues"}}, {"name": "projects", "endpoint": {"path": "rest/api/3/project/search", "data_selector": "values"}} ], } yield from rest_api_resources(config) def load_jira_to_mssql() -> None: pipeline = dlt.pipeline( pipeline_name="jira_pipeline", destination="mssql", dataset_name="jira_data", ) load_info = pipeline.run(jira_source()) print(load_info) if __name__ == "__main__": load_jira_to_mssql()
Run it with uv run python jira_pipeline.py. The agent iterates on this until it loads cleanly — you review and approve, rather than write it from scratch.
How do I query Jira data in Microsoft SQL Server?
dlt creates one table per resource. Query the loaded data with Python or SQL — or ask your agent to, through the MCP server's execute_sql_query tool.
Python (pandas DataFrame):
import dlt data = dlt.pipeline("jira_pipeline").dataset() df = data.issues.df() print(df.head())
SQL:
SELECT * FROM jira_data.issues LIMIT 10;
See querying your data with dataset and exploring it in marimo notebooks.
How do I deploy the Jira to Microsoft SQL Server pipeline in production?
The pipeline runs locally, which is ideal for prototyping and one-off analysis. When you need it on a schedule, monitored on every load, and shared with your team, deploy the same dlt code on the dltHub platform — no infrastructure to maintain. The prompt above already ends with "run it on dltHub", so your agent can take it there directly.
- Deploy & schedule — run the pipeline as a managed job with automatic retries.
- Monitor — observable job queues, alerting, and load metrics for every run.
- Transform — promote raw Jira loads into governed, documented models.
- Visualize & share — explore data in notebooks and publish live dashboards instead of static screenshots.
What other destinations can I load Jira data to?
dlt loads into any of these — only the destination argument changes:
| Destination | Example value |
|---|---|
| PostgreSQL | "postgres" |
| BigQuery | "bigquery" |
| Snowflake | "snowflake" |
| Redshift | "redshift" |
| Databricks | "databricks" |
| Filesystem (S3, GCS, Azure) | "filesystem" |
Set dlt.pipeline(destination="snowflake") and add credentials in .dlt/secrets.toml. On the dltHub platform the same pipeline runs against a managed Iceberg lakehouse. See the full destinations list.
Next steps
Was this page helpful?
Community Hub
Need more dlt context for Jira to Microsoft SQL Server?
Request dlt skills, commands, AGENT.md files, and AI-native context.