Tickets
Ledger can open a PSA ticket directly from an exception — one click, or up to 25 at once. Ticket creation is switched off unless it has been enabled for your account. Two things both have to be true before it does anything for a given customer: ticket creation has to be enabled for the account, and that customer has to have added its own ticket-creation connection — a connection created for that purpose alone, kept separate from an ordinary read connection, never a read connection widened into a write one. This page describes what happens once both of those are true, not what every customer sees right now.
The PSAs Ledger can write tickets to today are ConnectWise PSA and Autotask.
Data model
Every PSA ticket Ledger opens is recorded as its own entry, with these details:
| Detail | Meaning |
|---|---|
| Customer | Which Ledger customer (MSP) the ticket belongs to. Deleting the customer deletes the ticket record with it. |
| Exception | The exception the ticket was opened for. Deleting the exception deletes the ticket record with it. |
| Connection | Which PSA connection created the ticket. If that connection is later deleted or rotated, the ticket record is untouched: the PSA, ticket number and link are copied onto the record when the ticket is created, so losing the connection costs the record nothing it needs. |
| PSA | Which PSA the ticket lives in (for example ConnectWise PSA), recorded once, at create time. |
| PSA ticket number | The PSA's own ticket number, exactly as that PSA returned it. |
| Link | A direct link to the ticket in the PSA's own screen, when that PSA hands one back. Not every PSA does. |
| Status | Created (the ticket was opened) or failed (the attempt was not). |
| Device attached | Whether the ticket recorded a link to the specific device the exception was about. |
| Error | The failure detail, shown only when the status is failed. |
| Created by | The user or system process that triggered the creation. |
| Created at | When the record was written. |
One record is written per create attempt, successful or failed — never zero, and, per the one-active-ticket guarantee below, never more than one non-failed record at a time for the same exception.
What you actually see. The screen and its export don't carry every detail — they show the PSA, the PSA's own ticket number, a link to the ticket when the PSA handed one back, and the ticket's status (plus, as a tooltip on a failed row, the error). Who triggered a create is not shown on the exceptions screen; it is recorded instead in Ledger's own audit log, a separate surface from the exceptions list.
One active ticket per exception
Ledger never records two active tickets for one exception: a second non-failed ticket record for the same exception is refused. That is a guarantee about Ledger's own records, not about the PSA: no PSA offers a way to reject a duplicate ticket on its side, so if two create attempts for the same exception ever reached the PSA at the same moment, the PSA could end up holding a ticket Ledger has no record of; if you see one, contact support. A failed record does not count against the one-active-ticket rule -- retrying after a failure creates a new record rather than reusing the failed one.
Clicking create-ticket on an exception that already has an active ticket is never treated as a failure: Ledger hands back that existing ticket instead of calling the PSA a second time, so a device re-firing the same rule after its exception resolved -- and any other repeat click, whether from the same person or two people racing each other -- is never rejected. The response says as much, so the screen can tell you "this exception already has a ticket" instead of "Ticket created" without you ever seeing an error.
"Active" here means exactly "not failed" -- it says nothing about whether the underlying exception is open, suppressed, acknowledged, or resolved. Filing a ticket and managing the exception's own lifecycle are independent actions: creating a ticket never changes the exception's own status (see Exceptions).
One click, and up to 25 at once
The exceptions screen offers a Create ticket action on any row that has a ticket-creation connection to use, and a Create tickets (n) bulk action once you've selected some rows with the checkboxes. Both open the same dialog: pick the connection (skipped automatically when you only have one), then the board, priority, and — once a board is chosen — type (see the next section).
The bulk action is capped at 25 exceptions per click. That's well below the 500-at-a-time cap on bulk-suppressing exceptions, and deliberately so: bulk-suppress only changes Ledger's own records, while each exception in a bulk ticket-create is a real request to your PSA's own API. The per-hour and per-minute rate limits described under "Rate limits," below, exist for the same reason.
A bulk create attempts every selected exception one at a time, never in parallel, and reports back
in two buckets that mean different things: an exception counts as not attempted when Ledger
itself never called your PSA for it and never will for this request (for example, its client isn't
mapped to a PSA company). An exception that already has an active ticket counts as created
instead, alongside the ones the PSA genuinely just accepted — its own ticket says as much (it
already had one, so nothing new happened on the PSA), the same "no error, just tell you what's
true" treatment two create attempts racing for the same exception get too (see "One active ticket
per exception," above, where the losing attempt's own PSA call actually succeeded and Ledger hands
back the row that won the race rather than dropping it or calling it a failure). An exception that
Ledger did call your PSA for, but which the PSA rejected, also counts as created — with that
ticket's own status reading failed. The confirmation you see after a bulk create breaks all of
this apart explicitly: how many landed on the PSA, how many already had a ticket, how many the PSA
rejected, how many were never attempted, and how many of the successful ones were filed while the
underlying source data was stale (see "Staleness," below).
Rate limits
Each customer can have at most 100 tickets created per hour and 20 per minute. The count covers every ticket Ledger recorded for the customer in that window, including the ones whose create attempt the PSA rejected (failed) — Ledger still made a request to your PSA for each of those. Asking for a ticket on an exception that already has one is never refused either.
At the limit, creating a single ticket answers "ticket creation rate limit exceeded" and says how many seconds until a slot is free: about a minute if the per-minute limit was reached, but up to an hour if the per-hour limit was, because that window only clears as its oldest tickets age out. A bulk create can be refused part of the way through: the bulk cap of 25 is higher than the 20-per-minute limit, so a full 25-exception request stops creating after the 20th and lists the rest as not attempted, with that same message — nothing was sent to your PSA for them, and you can select them again once the limit has cleared (about a minute for the per-minute limit; longer for the hourly one).
Per-client defaults
Board, priority, and type can be saved once per client, per connection, so a repeat customer's
create-ticket dialog opens pre-filled instead of asking you to re-pick the same three values every
time. Check "Use these settings as <client>'s default" in the dialog and it's saved the
moment the ticket you're creating actually lands on the PSA — never on a vendor-rejected create, so
a bad board id you typo'd once never becomes anyone's saved default. The checkbox itself only shows
up when the ticket you're creating resolves to exactly one client: a single-exception create does
whenever that exception has a client; a customer-wide exception (no client at all) has nothing to
save a default against, so the checkbox stays hidden the same way it does for a bulk selection
that spans more than one client.
Saving a default only changes Ledger's own records — no PSA is called — so it works even while ticket creation is not enabled for your account; only creating an actual ticket needs it enabled. Defaults are stored on the client itself, keyed by which connection they're for, so a client with two ticket-creation connections can have a different default board/priority/type saved against each one.
Ticket type depends on picking a board first
Board and priority load as soon as you pick a connection — they don't depend on anything else you choose in the dialog. Type (and status, which the dialog doesn't ask for) is different: your PSA only tells Ledger which types exist for a given board, so the type dropdown stays disabled, reading "Choose a board first," until you pick one. Once that board's types have loaded, the dropdown enables — unless that particular board genuinely has none, in which case it stays disabled and reads "No ticket types available" instead. Switching boards clears whatever type you'd picked for the old one, since a type id is only ever meaningful for the board it came from.
If creation fails
A failed vendor call surfaces to you immediately, as an error — Ledger never automatically retries a failed ticket-creation attempt: no PSA here offers a server-enforced dedupe guarantee, so an automatic retry risks opening a genuine second ticket on the PSA's own side. The failed attempt is itself recorded as a failed ticket record carrying what the vendor, or the validation before it, reported, and the row shows up on screen as a red "Ticket failed" badge carrying that error as its tooltip — a single failed create closes the dialog and surfaces the same message in a banner above the table, rather than a generic "something went wrong."
You may click create-ticket again. The one-active-ticket rule (see "One active ticket per exception" above) only blocks a second non-failed record for the same exception, so a retry after a failure creates a brand-new record rather than reusing, or being blocked by, the failed one. A retry attempted while the exception already has an active (non-failed) ticket never reaches the vendor and is never recorded as a second attempt of any kind, failed or otherwise: Ledger hands back that existing ticket instead (see "One active ticket per exception" above).
Staleness
A ticket's staleness looks at every data source the exception's own rule actually reads — not the rule's own category (Security, Billing, Hygiene, or Lifecycle; a different vocabulary) — and comes back true if any one of those sources is currently stale, the same per-category staleness Exceptions itself tracks. When it's true, a ticket created from that exception says so at the moment it's created: the single-create toast reads "Ticket created — source data was stale when it was filed," and a bulk create's own confirmation counts how many of the tickets it just filed were stale. This is worked out fresh, at the moment of the click — never stored on the ticket, so re-opening an old ticket never reports a staleness value for it after the fact.
Screen and export parity
Once an exception has a ticket, the exceptions screen and its CSV/XLSX export both show its PSA ticket number, link, and status — read from the same data, so the two surfaces can never disagree about which ticket an exception has. Every export, this one included, also neutralizes a cell that would otherwise start a spreadsheet formula — see Exports for exactly how, rather than restating it here.
That guarantee does not reach every place exceptions are summarized, though: the scheduled report's own "Top open exceptions" table is a separate, fixed four-column render (device, rule, severity, client), built the same way for every customer whether or not they use ticket creation, and it does not carry a ticket column.
Lifecycle rules
Creating a PSA ticket and managing the exception it came from are two independently-writable facts about the same row -- neither one ever drives the other. Creating a ticket never changes the exception's own status (see "One active ticket per exception," above, and Exceptions for that same rule from the exception screen's own point of view); the rest of this section is the other half -- what happens to Ledger's own records once the ticket itself moves.
Resolving, closing, or otherwise changing a linked PSA ticket writes nothing back into Ledger. Ledger reads a PSA ticket exactly once -- at the moment it's created, to record the vendor's own ticket number and a link back to it -- and never checks the ticket again after that. And resolving, suppressing, or acknowledging the Ledger exception writes nothing back to the PSA ticket either: no status change, no note, nothing at all. The two lifecycles are tracked independently, by design. Writing a note back to the PSA ticket would be a second, distinct write action, which Ledger deliberately doesn't do.