Write your own plugins against the ticketing API.
Most help desk products hand you a webhook and a button. The button fires, something happens in another system, and a week later nobody can say who triggered it or what came back.
Latch Workflow gives you an SDK instead. You write two functions, discover and execute. The platform runs the permission check, the approval step, and the audit entry around them. TypeScript and Go, both deployed as your own service inside your own network — and the same plugin interface is how you attach your own model endpoint.
discover → authorize → execute → reflect
Add downstream actions without shipping a core release
Teams should not need a product release every time a new downstream action matters. Plugins keep the ticketing system extensible while the boundary around permissions, execution, and audit history stays in one place. The object your plugin receives is a ticket — or a case, if you work in a regulated function — with its fields, history, and current approval state.
If your team is building internal tools around custom APIs, payment systems, or private models, see how the same SDK fits platform teams weighing build against buy, and what the plugin system already covers.
Use the SDK that fits your stack instead of hand-rolling discovery and execution contracts against the API.
The platform stays responsible for permissions and operator context, even when the action runs elsewhere.
Plugins are your processes on your hosts. On-prem, private cloud, or air-gapped, the ticket data never has to leave the network to reach one.
export async function discover(ctx) {
// Only show the action when the ticket context says it matters.
if (ctx.ticket.issue_type?.name !== 'Payment Reprocess') {
return [];
}
return [{
id: 'reprocess-payment',
label: 'Reprocess Payment',
description: 'Run the external reprocess flow from the ticket.',
requires_confirmation: true,
}];
}
export async function execute(actionId, ctx) {
// The platform stays responsible for permissions and auditability.
return {
success: true,
message: 'Payment reprocess submitted.',
effects: {
add_comment: {
content: 'External reprocess started from plugin.',
is_public: false,
},
change_status: {
status: 'In Progress',
},
},
};
}A webhook that carries the decision, not just the event
Most ticketing system webhooks tell your service that a status changed and leave it to call back for everything else. Your service then acts without knowing who authorised the work.
Latch signs every delivery and includes the ticket, the action, the operator who requested it, and the reviewer who approved it. Your service acts on one payload, and your own logs can show why it acted.
X-Latch-Signature: sha256=6f1c...
{
"event": "ticket.action.approved",
"ticket": {
"id": "TKT-4182",
"queue": "payment-exceptions",
"issue_type": "Payment Reprocess"
},
"action": {
"id": "reprocess-payment",
"requested_by": "a.mensah",
"approved_by": "j.okafor"
},
"occurred_at": "2026-03-11T09:41:22Z"
}export const model = defineModelPlugin({
// Any endpoint you control: an open-weights model
// on your own GPU, or a vendor API with your key.
baseUrl: process.env.MODEL_BASE_URL,
apiKey: process.env.MODEL_API_KEY,
jobs: {
// small local model, runs in the rack
triage: process.env.TRIAGE_MODEL,
// stronger model for field extraction
extract: process.env.EXTRACT_MODEL,
},
});Open a ticket from a monitoring alert, attach evidence to an existing one, move an item between queues, change an assignee, or export the audit trail. The operator UI calls the same endpoints your service can call.
If all you want is to open a ticket from an alert, the API is enough and a plugin is overhead. Plugins earn their place when the action runs on an external system and needs a role check, an approval step, or a record of what came back.
Implementation questions developers ask
These answers cover the SDK, where plugins run, model endpoints, webhook payloads, authentication, testing, and error handling — the details that matter when you are writing the code.
What languages does the help desk SDK support?
TypeScript and Go. Both SDKs handle the discovery and execution contract, so the plugin code focuses on the action logic — not on serialization, auth handshakes, or response formatting.
Where do plugins and the SDK actually run?
In your environment. A plugin is your own service, deployed next to the ticketing system on-prem, in your private cloud, or inside an air-gapped network. Latch calls it over your network. No ticket data has to cross your boundary for a plugin to work, which is what keeps data residency rules intact.
Can I point the SDK at my own model endpoint?
Yes. The model is configured as a plugin like any other integration: a base URL, a key, and a model name per job. Point it at an open-weights model running on your own hardware, at a vendor API with your own key, or at different endpoints for triage and extraction. Swapping models is a configuration change, not a migration.
How are ticketing API and plugin calls authenticated?
HMAC signatures, API keys, or bearer tokens. Latch routes execution through its own permission and approval checks instead of exposing a raw button-to-webhook flow, and the SDK verifies signatures on inbound deliveries for you.
What do ticketing system webhooks contain?
Each delivery is signed and carries the ticket, the action, the operator who requested it, the reviewer who approved it, and the timestamp. Your service can act on the payload without calling back for context, and your own logs can show why it acted.
Can a plugin return side effects?
Yes. A plugin can return effects such as comments, status changes, or structured field updates, and Latch applies and records them atomically. The plugin never writes directly to the ticket — it declares what should change.
How do I test a plugin locally?
The SDK includes a local test harness that simulates ticket context, role checks, and execution without a running Latch instance. You can also point a dev environment at a staging plugin endpoint for end-to-end testing.
What happens when a plugin times out or returns an error?
The failure response writes to the ticket timeline with the status code, error message, and timestamp. The operator sees exactly what happened. Retries are manual — the operator can re-trigger the action after reviewing the failure.
Bring one plugin action into the ticket
Pick the workflow your team relies on most and see how a plugin exposes it inside the ticket, with the role check and approval step already around it.