TicketSync
Bidirectional ticket synchronization across ITSM, monitoring, and security systems.
TicketSync is a Python library, not a platform. You pip install it and use it in code.
No daemons, no YAML platform to self-host, no vendor lock-in.
Install
pip install ticketsync
For AWS adapters (CloudWatch, GuardDuty, Security Hub, OpsCenter):
pip install "ticketsync[integration]"
Requires Python 3.10+.
Quickstart — CloudWatch alarms into OpsCenter in 15 lines
import boto3
from ticketsync.adapters.cloudwatch_alarms import CloudWatchAlarmsAdapter
from ticketsync.adapters.opscenter import OpsCenterAdapter
from ticketsync.config import SyncConfig
from ticketsync.engine import SyncEngine
source = CloudWatchAlarmsAdapter(
client=boto3.client("cloudwatch", region_name="us-east-1"),
state_filter=["ALARM"],
)
dest = OpsCenterAdapter(
client=boto3.client("ssm", region_name="us-east-1"),
)
config = SyncConfig.from_dict({
"source": {"type": "cloudwatch_alarms"},
"destination": {"type": "opscenter"},
"deduplication": True,
"lookback_hours": 24,
})
engine = SyncEngine(source=source, dest=dest, config=config)
result = engine.run()
print(f"Synced {result.written} alarms to OpsCenter")
Adapter table
| Adapter class | System | Direction | Required IAM / auth |
|---|---|---|---|
CloudWatchAlarmsAdapter |
AWS CloudWatch Alarms | read | cloudwatch:DescribeAlarms |
GuardDutyFindingsAdapter |
AWS GuardDuty Findings | read | guardduty:ListFindings, guardduty:GetFindings |
SecurityHubFindingsAdapter |
AWS Security Hub (ASFF) | read | securityhub:GetFindings |
OpsCenterAdapter |
AWS Systems Manager OpsCenter | read/write | ssm:GetOpsItem, ssm:CreateOpsItem, ssm:UpdateOpsItem |
GitHubIssuesAdapter |
GitHub Issues REST API | read/write | GitHub PAT with repo scope |
LocalFilesystemAdapter |
Local JSON files | read/write | None |
Config YAML reference
source:
type: cloudwatch_alarms # adapter type key (see table above)
# any extra keys are passed as kwargs to the adapter constructor
destination:
type: opscenter
region: us-east-1
deduplication: true # skip tickets already written to destination
lookback_hours: 24 # only sync tickets updated in last N hours (0 = all)
Load config from a YAML string, file path, or open file object:
from ticketsync.config import SyncConfig
config = SyncConfig.from_yaml("path/to/sync.yaml")
# or
config = SyncConfig.from_dict({"source": {...}, "destination": {...}})
Example — GuardDuty findings into GitHub Issues
import boto3
import httpx
from ticketsync.adapters.guardduty import GuardDutyFindingsAdapter
from ticketsync.adapters.github_issues import GitHubIssuesAdapter
from ticketsync.config import SyncConfig
from ticketsync.engine import SyncEngine
class HttpxClient:
"""Thin httpx wrapper matching the GitHubIssuesAdapter client interface."""
def __init__(self, token: str) -> None:
self._headers = {"Authorization": f"Bearer {token}"}
def get(self, url: str, params: dict | None = None) -> object:
return httpx.get(url, params=params, headers=self._headers).json()
def post(self, url: str, json: dict | None = None) -> dict:
return httpx.post(url, json=json, headers=self._headers).json()
def patch(self, url: str, json: dict | None = None) -> dict:
return httpx.patch(url, json=json, headers=self._headers).json()
source = GuardDutyFindingsAdapter(
client=boto3.client("guardduty", region_name="us-east-1"),
detector_id="your-detector-id",
)
dest = GitHubIssuesAdapter(
client=HttpxClient("ghp_your_token"),
owner="your-org",
repo="security-issues",
)
config = SyncConfig.from_dict({
"source": {"type": "guardduty"},
"destination": {"type": "github_issues"},
"deduplication": True,
"lookback_hours": 6,
})
result = SyncEngine(source=source, dest=dest, config=config).run()
print(f"Opened {result.written} GitHub issues from GuardDuty findings")
Core data model
Every ticket, alarm, finding, and issue is normalized to the Ticket IR before
moving between adapters:
from ticketsync.models import Ticket
ticket = Ticket(
source_system="guardduty",
source_id="abc123",
title="Suspicious API call from known malicious IP",
description="GuardDuty detected an unusual API call pattern.",
severity="high", # critical / high / medium / low / informational
status="open", # open / in_progress / resolved / closed
category="Recon:EC2/Portscan",
tags=["region:us-east-1", "product:GuardDuty"],
)
See docs/ARCHITECTURE.md for the full field reference.
Documentation
- docs/ADAPTERS.md — required permissions, field mapping tables, and config examples for every adapter
- docs/ARCHITECTURE.md — Ticket IR fields, Protocol interface, SyncEngine behavior, deduplication logic
- docs/CONTRIBUTING.md — how to write a new adapter, test patterns, registry entry
License
Apache 2.0
Release files for ticketsync 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ticketsync-0.3.1.tar.gz | 80.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ticketsync-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 121.1 kB
Release files / ticketsync-0.3.1.tar.gz
| Download URL | ticketsync-0.3.1.tar.gz |
|---|---|
| Size | 80.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6ee409edeef1359dad206d5b84bc98b38ad5f91020e0198c2a78199e4d318a35
|
|
BLAKE2b-256 checksum How to use checksums |
a4b0dde46800eeccfd2874007b6b5d81c2794dc1617562cba2718d61806c2c73
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 9, 2026.
Transparency logRelease files / ticketsync-0.3.1-py3-none-any.whl
| Download URL | ticketsync-0.3.1-py3-none-any.whl |
|---|---|
| Size | 40.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ac84a29ffc1343422ed0ba323c3daf5c7de6424b309ebc0f5d2bbf8434b1743e
|
|
BLAKE2b-256 checksum How to use checksums |
c16b956cb338b92aeef8298523bbe84409e581b43516fe5b28014c68daeabbb0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 9, 2026.
Transparency log