Helpers and the Semantic Layer in TypeScript
Use the helper methods (ensure, find, update, resolve, createApi …) for multi-call tasks, and planRotation / planEscalation plus ao.semantic.applyBlueprint to build a verified on-call stack that rolls back on failure.
Overview
Relevant for Developers automating multi-step AlertOps configuration
Helpers are composite operations that sit on the same resources as the endpoints. Examples:
- ao.groups.ensure (find or create).
- ao.schedules.updateFields (read, merge, write the whole shift).
- ao.alerts.resolve (close, or cancel what cannot be closed).
The semantic layer goes further: pure planners turn intent ("after-hours rotation, primary then secondary after 15 minutes") into exact payloads that follow AlertOps' scheduling and escalation invariants. An executor then applies them, verifies every write by reading it back, and rolls back on failure. All of it is ported from the Python reference and replays Python's recorded traces.
Key benefits:
- Fewer calls to get right: whole-record writes, alert_type naming and member sequencing are handled for you.
- Invariants enforced:
- Shifts end on :59.
- Starts align to the prior Monday.
- End dates are 5 years out.
- The escalation ladder starts with Primary.
- Safe to apply: drift is reported, and a failed blueprint deletes what it created.
Helper conventions
Relevant for Developers calling helpers
Helpers take Python's positional parameters as arguments. Keyword-only parameters and extra fields go in one trailing options object, keyed by the Python names. Examples:
- ao.alerts.listRecent(3, { view_all: false, status: "Open" }).
- ao.inbound.createApi("Prod API", { escalation_policy_id: 5, recipient_groups: ["NOC"] }).
| Helper | What it does |
| ao.groups.ensure(name, fields?) | Returns [group, created]. |
| ao.users.findByUsername(name) | The user, or null (maps 400 "Invalid User" and 404). |
| ao.escalationPolicies.update(id, changes) | GET basic, then merge, then PUT the whole record. Returns the re-read record. |
| ao.schedules.createShift(groupId, name, users, options) | Builds an invariant-clean shift (shiftPayload) and resolves an IANA time_zone. |
| ao.inbound.createApi(name, options) | API integration with a unique source. A random one is used if omitted. |
| ao.ingest.postToUrl(apiUrl, payload) | Posts an alert payload to an integration URL. Returns the request id. |
| ao.alerts.resolve(alertId, userId, resolution?) | Closes the alert, or cancels it when it cannot be closed. |
| ao.auth.actOnLink(link) | Runs the action behind a notification link (acknowledge, assign, escalate, close). This is how acknowledgement works end to end. |
The inbound integration URL routes by source
Two integrations with the same source share an ingest URL, and alerts can land on the wrong one. createApi and cloneUnique always give each integration its own source.
Plan a rotation and an escalation
Relevant for Developers turning on-call intent into configuration
Planners make no API calls. Inspect their output before you apply it.
import { coverage, member, planEscalation, planRotation, rotationSpec, step, validateDesign } from "@alertops/sdk";
const rotation = planRotation(rotationSpec("NOC", [member(101, "Ann", "Lee"), member(102, "Bo", "Ma")],
{ coverage: coverage("after_hours") })); // Mon–Fri 17:00 → 07:59, weekly rotation
const escalation = planEscalation([step(0, "primary", 101), step(5, "primary", 102), step(15, "secondary", 101)]);
console.log(escalation.mode, escalation.reason); // escalation_policy, "Escalation policy Primary → Secondary …"
console.log(validateDesign(rotation, escalation)); // [] when clean
planEscalation chooses an escalation policy when the timeline fits its four timing levers. It falls back to a response play, with per-step waits, when it doesn't: more than 4 distinct intervals, or unequal gaps within one role.
Apply a verified stack
Relevant for Developers creating an on-call setup in a tenant
import { blueprint, integrationSpec } from "@alertops/sdk";
const report = await ao.semantic.applyBlueprint(blueprint("NOC", {
rotation, escalation, integration: integrationSpec("NOC API"),
}));
console.log(report.summary()); // OK: created 4 … (+ group, + schedule, + escalation_policy, + inbound_integration)
if (!report.ok) console.log(report.drift);
await ao.semantic.rollback(report); // remove everything the report created
| Report field | Meaning |
| created / reused | Objects made by this call, and objects it found and reused. Rollback only deletes created. |
| drift | Differences between the plan and what the tenant read back. ok is false when there is any drift. |
| review_items | Planner and validator notes. block items stop the apply. |
| rolled_back | True after rollback. |
Blocking review items stop the apply
A blueprint whose integration has no escalation policy, or a rotation with no Primary in week 1, throws ValueError before anything is created.
Troubleshooting
Relevant for Anyone whose helper or apply fails
ValueError: group has a shift: roles are set on the shift
- Once a group has a shift, AlertOps rejects Primary and Secondary on members. Call ensureMembers without roles, or with ["Manager"].
The report shows drift
- Read the drift line: it names the field, the planned value and the value read back. A shift that reads back continuous=True was saved differently by the server. Adjust the plan and apply again.
Related Articles
- Calling the API from TypeScript
- Getting Started with the AlertOps TypeScript SDK
- Testing the TypeScript SDK
- Planning On-Call Setups with the AlertOps Semantic Layer
Need help?
Email support@alertops.com or contact your AlertOps representative.