Resolve Atera tickets generated by alerts when the underlying alerts are resolved.
- Python 3.12
- httpx, pydantic, tenacity, typer
- Docker for packaging
The API key is read from .env as ATERA_API_KEY and passed into Docker via env_file.
Ticket comments require ATERA_TECHNICIAN_ID in .env (existing Atera technician ID).
Example .env:
ATERA_API_KEY=...
ATERA_TECHNICIAN_ID=2
# Optional (included in comment payload if set):
ATERA_TECHNICIAN_EMAIL=tech@example.comIf you have uv:
uv venv
uv pip install -e .Otherwise:
python -m venv .venv
source .venv/bin/activate
pip install -e .Local:
source .venv/bin/activate
atera-sync testDocker:
docker compose run --rm atera-sync testThis fetches tickets 9981 and 9956, prints a redacted summary (ticket id, status, source, alert id), and saves full JSON to fixtures/.
If any request fails, it prints the status code + response body and exits nonzero.
If ticket fixtures do not include alert ids, fetch an alert by id and save a sample fixture:
atera-sync alert-sample <alert_id>Export full open alerts list:
atera-sync alerts-exportLocal:
source .venv/bin/activate
atera-sync run 100 14Docker:
docker compose run --rm atera-sync run 100 14Run arguments are positional:
atera-sync run <max_alerts> <days_back>
pytestTests load fixtures from fixtures/. Run the test command first to populate ticket fixtures:
docker compose run --rm atera-sync test0 8-18 * * * cd /home/docker/AteraAlertResolver && /usr/bin/docker compose run --rm atera-sync run 100 14 >> /home/docker/AteraAlertResolver/sync.log 2>&1Create a daily task that runs hourly from 08:00 to 18:00 with the action:
docker compose run --rm atera-sync run 100 14
Set the “Start in” directory to:
C:\path\to\AteraAlertResolver
- Alerts are listed with status
Resolvedduringatera-sync runand used to discover related ticket ids. atera-sync runuses positional args (max_alerts days_back); current production setting is100 14.- If older resolved alerts were missed (for example after downtime/backlog), run a one-off catch-up with
atera-sync run 500 14, then return to100 14. - Alerts are actionable only when severity is
WarningorCritical;Informationalerts are skipped. - Pagination uses
itemsInPage=50and followsnextLinkuntil empty, accumulatingitems. max_alertsis applied during pagination to avoid pulling full alert history when capped.- For each resolved alert, full alert details are fetched to extract linked
ticketId. - Alerts are considered actionable only if alert status equals
resolved(case-insensitive), with fallback to the list filter status when not present. - Before closing a ticket, automation posts the comment:
alert resolved, closing ticket by automation. - Tickets are updated to
Resolvedonly if not already in terminal statesResolved/Closed/Merged/Deleted. - Each ticket is processed at most once per run even if multiple resolved alerts reference the same ticket.
- End-of-run summary logs include:
alertsReviewedticketsActionedupdatedTickets