REST API
MSP Align has a REST API for automation tools (n8n, Zapier, Power Automate), AI agents, scripts and other systems. It reads and changes planning data: clients, contacts, devices, projects, budgets, licensing, meetings, compliance, alignment reviews, health scores, backups, service levels and vendors. JSON in and out.
Alignment (2.3.0) has its own scope, alignment:read / alignment:write. Keys made before 2.3.0 don't have it:
edit the key under Settings → API and tick Alignment.
Vendors (2.10.0) are read-only, with their own scope vendors:read: GET /vendors (each client's vendors as its
Vendors page shows them; client_id, category, include_retired, updated_since), GET /vendors/{id} and
GET /vendor-templates. Keys made before 2.10.0 don't have it: edit the key under Settings → API and tick Vendors.
What changed (2.4.0): GET /clients/{id}/changes returns what changed since the client's last completed business
review (or ?since=m<meeting id> / ?since=YYYY-MM-DD). It needs clients:read; each part (devices, projects,
alignment, compliance, licenses, backups, tickets) is included only when the key can read that area.
Health score (2.5.0) has its own scope, health:read. Keys made before 2.5.0 don't have it: edit the key under
Settings → API and tick Health score. GET /clients/{id}/health returns the score, band and each area's score;
an area's details (what pulls it down) come only when the key can also read that area. GET /clients/{id}/health/history
returns one entry per day (?days=, default 90).
The reference below is generated from the same route table and validation rules the API itself uses, so it always
matches the release it was built from. Your own server has the same reference under Settings → API → API reference,
and serves the machine-readable description at https://<your server>/api/v1/openapi.json.
Download the OpenAPI description (OpenAPI 3.1) for this release.
Getting started
- Turn it on: Settings → API → Turn on (admins only; it's off on a new install).
- Create a key: give it a name, the scopes it needs (read or write per area), and optionally limit it to some
clients, set an expiry and a per-minute rate limit. The key (
msa_…) is shown once; only a hash is kept. - Call it: the base URL is
https://<your server>/api/v1.
export ALIGN_KEY="msa_…"
curl -s -H "Authorization: Bearer $ALIGN_KEY" https://align.example.com/api/v1
curl -s -H "Authorization: Bearer $ALIGN_KEY" "https://align.example.com/api/v1/devices?attention=true&per_page=20"
- n8n, Zapier, Power Automate: an HTTP Request step with the header
Authorization=Bearer msa_…. - AI agents: give them the OpenAPI description and a key with only the scopes they need.
- Every change is in the audit log under the key's name, and every request in the key's 30-day request log.
- A key stops working when the admin who created it is disabled or is no longer an admin.
Ids
idis MSP Align's own id for a record: a number.- Ids from your PSA are text (since 2.0):
psa_idon clients, contacts and licenses, andpsa_asset_idon devices, for example"57"for ITFlow. A PSA that uses other kinds of ids (GUIDs, for example) fits the same field. - The older
itflow_*fields (itflow_client_id,itflow_contact_id,itflow_asset_id, …) are still there, as numbers, so integrations written for 1.x keep working.
Upgrading an integration from 1.x: before 2.0,
psa_idwas a number for ITFlow (57); now it is text ("57"). If a flow or script comparespsa_idwith a number, compare it as text or use theitflow_*field instead.
Compatibility
The API is versioned in its path (/api/v1). From 2.0 on, changes to v1 only add things: new endpoints, new fields in
responses and new optional fields in requests. Ignore fields you don't know, rather than failing on them. Anything that
would break an integration will come as a new version (/api/v2), announced in What's new,
with v1 kept alongside it.
Permissions (scopes)
Each key has read or write access per area; write includes read.
| Area | Read (area:read) | Write (area:write) |
|---|---|---|
Clientsclients | Clients, their details and a health summary | read only |
Contactscontacts | Client contacts and their roles | read only |
Devices & lifecycledevices | Devices with lifecycle status, warranty, OS support and replacement cost | Purchase / in-service and warranty dates, lifespan, replacement cost, planned replacement quarter, type, exclusion and notes |
Projects & roadmapprojects | Roadmap projects and their status | Create, change and delete projects (title, quarter, cost, priority, status) |
Budgetbudget | Technology budget by quarter and category, and budget lines | Create, change and delete budget lines |
Licensinglicenses | Licenses with prices, contract dates and renewals | Prices, billing cycle, contract dates and notes; add, retire and delete licenses you added |
Vendorsvendors | Client vendors (account numbers, support details, services, notes) and vendor templates (2.10.0) | read only |
Meetingsmeetings | Meetings, agendas and notes | Schedule, change, complete, cancel and delete meetings (optionally sending calendar invitations) |
Compliancecompliance | Frameworks, scores and each control's status | Control status, notes, evidence, owner and due date; assign and remove frameworks |
Alignmentalignment | Standards, clients' alignment scores, gaps and reviews with their answers | Start reviews, answer standards, finish and discard reviews (2.3.0) |
Backupsbackups | Backup status, jobs, protected machines and hosted backups | "Not required" exemptions and hosted backup assignments |
Service levelsservice | SLA results from PSA tickets | read only |
Health scorehealth | Clients' health scores, each area's score and the daily history (2.5.0) | read only |
Errors
| Status | error.code | Meaning |
|---|---|---|
| 400 | invalid_json, invalid_idempotency_key | The request body or a header is malformed. |
| 401 | missing_key, invalid_key, key_expired, key_revoked, key_owner_inactive | No usable API key (a key stops when the staff account that created it is disabled or is no longer an admin). |
| 403 | insufficient_scope, all_clients_required | The key lacks the permission (see the X-Required-Scope header). |
| 404 | not_found, api_disabled, no_backup_data, no_service_data | Not found, or outside the clients the key is limited to. |
| 405 | method_not_allowed | See the Allow header. |
| 409 | idempotency_conflict, idempotency_in_progress, managed_in_itflow (managed_in_<PSA key> for other PSAs), not_enabled | The request conflicts with the current state. |
| 413 | body_too_large | Bodies are limited to 1 MB. |
| 415 | unsupported_media_type | Send JSON with Content-Type: application/json. |
| 422 | validation_failed | error.fields names each problem. |
| 429 | rate_limited, too_many_failed_requests | Wait for Retry-After seconds. Requests without a valid key are also limited per IP address. |
| 500 | internal_error | Logged on the server with the request_id. |
{"error": {"code": "validation_failed", "message": "Some fields are not valid.", "fields": {"cost": "Must be a number."}}, "request_id": "9f2c41d0a7b3e815"}Endpoints
Meta
/api/v1About this key
The key's name, scopes, client limit, expiry and rate limit. A cheap way to test a key.
Response: Key
The API key making the request.
| Field | Type | |
|---|---|---|
name | string | Name given to the key. |
prefix | string | Public part of the key. |
scopes | array of string | Permissions, e.g. projects:write. |
client_ids | array of integer | Clients the key is limited to; null = all clients. |
rate_limit_per_minute | integer | |
expires_at | date-time | null = never. |
api_version | integer | |
app_version | string | |
openapi | string | Path of the OpenAPI document. |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1Clients
/api/v1/clientsclients:readList clients
| Parameter | Type | |
|---|---|---|
search | string | Name contains. |
include_excluded | boolean | Include clients taken out of planning. |
updated_since | string | Only items changed since this date/time (ISO 8601). Use it to sync incrementally. |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Client
A client (details come from the PSA and are read-only).
| Field | Type | |
|---|---|---|
id | integer | |
name | string | |
industry | string | |
source | string | The PSA's key (e.g. itflow) or manual. |
psa_id | string | The client's id in the PSA, always as text (e.g. "57" for ITFlow). Since 2.0; before, a number for ITFlow. |
itflow_client_id | integer | Older name for psa_id, kept for existing integrations. |
main_phone | string | |
website | string | |
address | string | |
primary_contact | object | name, title, email, phone, mobile. |
vcio | object | Staff user who is vCIO for the client: id, name. |
meeting_cadence | string | How often you meet. |
in_planning | boolean | false = taken out of planning. |
created_at | date-time | |
updated_at | date-time | |
url | string | Link to the client in the web app. |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/api/v1/clients/{id}clients:readGet a client with its health summary
The summary has a section for each area the key can read: devices, projects, next meeting, backups, compliance and service levels.
Response: ClientDetail
A client plus a health summary.
| Field | Type | |
|---|---|---|
id | integer | |
name | string | |
industry | string | |
source | string | The PSA's key (e.g. itflow) or manual. |
psa_id | string | The client's id in the PSA, always as text (e.g. "57" for ITFlow). Since 2.0; before, a number for ITFlow. |
itflow_client_id | integer | Older name for psa_id, kept for existing integrations. |
main_phone | string | |
website | string | |
address | string | |
primary_contact | object | name, title, email, phone, mobile. |
vcio | object | Staff user who is vCIO for the client: id, name. |
meeting_cadence | string | How often you meet. |
in_planning | boolean | false = taken out of planning. |
created_at | date-time | |
updated_at | date-time | |
url | string | Link to the client in the web app. |
summary | object | devices {total, healthy, past_end_of_life, unsupported_os, out_of_warranty}, projects {active, awaiting_decision}, next_meeting, backups {health, jobs, failed_jobs, ...}, compliance {frameworks, average_score}, alignment {score, band, reviewed_at, gaps} (2.3.0), service_levels_90d. Only the sections the key can read. |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/api/v1/clients/{id}/changesclients:readWhat changed since the last review
Projects finished, devices replaced, added and removed, warranties, end of life and OS support that ran out, alignment and compliance changes, licenses and tickets since the starting point. Each part is included only when the key can read its area (tickets need service:read). Then-figures come from the snapshot saved when the review was completed (since 2.3.0); without one they are null.
| Parameter | Type | |
|---|---|---|
since | string | m |
Response: Changes
What changed for a client since a business review (2.4.0).
| Field | Type | |
|---|---|---|
client_id | integer | |
since | object | key, meeting_id, date, at, label, days, snapshot (then-figures saved at that review). |
baselines | array of object | Completed reviews to compare with, newest first. |
headline | array of object | tone, title, text: a short summary. |
devices | object | now, then, counts and lists: added, removed, replaced, warranty_expired, became_due, os_ended (devices:read). |
projects | object | counts and lists: done, added, approved, started, declined (projects:read). |
spend | object | done_cost, done_monthly, slipped (projects:read). |
alignment | object | then, now, change, closed and opened gaps (alignment:read). |
compliance | object | frameworks with now, then, change, updated (compliance:read). |
licenses | object | now, then, added, retired (licenses:read). |
backup | object | now, then (backups:read). |
tickets | object | opened, closed, still_open, categories (service:read). |
url | string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/changesContacts
/api/v1/contactscontacts:readList contacts
| Parameter | Type | |
|---|---|---|
client_id | integer | Only this client. |
role | string | primary, billing, technical, important, decision_maker or meeting_invitee. |
search | string | Name or email contains. |
include_archived | boolean | Include archived contacts. |
updated_since | string | Only items changed since this date/time (ISO 8601). Use it to sync incrementally. |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Contact
A client contact.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
name | string | |
title | string | |
department | string | |
email | string | |
phone | string | |
extension | string | |
mobile | string | |
location | string | |
roles | array of string | primary, billing, technical, important, decision_maker, meeting_invitee. |
notes | string | Align notes. |
source | string | |
psa_id | string | The contact's id in the PSA (text, as psa_id on clients). |
itflow_contact_id | integer | Older name for psa_id, kept for existing integrations. |
archived | boolean | |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/contacts/api/v1/clients/{id}/contactscontacts:readList a client's contacts
| Parameter | Type | |
|---|---|---|
role | string | Filter by role. |
search | string | Name or email contains. |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Contact
A client contact.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
name | string | |
title | string | |
department | string | |
email | string | |
phone | string | |
extension | string | |
mobile | string | |
location | string | |
roles | array of string | primary, billing, technical, important, decision_maker, meeting_invitee. |
notes | string | Align notes. |
source | string | |
psa_id | string | The contact's id in the PSA (text, as psa_id on clients). |
itflow_contact_id | integer | Older name for psa_id, kept for existing integrations. |
archived | boolean | |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/contacts/api/v1/contacts/{id}contacts:readGet a contact
Response: Contact
A client contact.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
name | string | |
title | string | |
department | string | |
email | string | |
phone | string | |
extension | string | |
mobile | string | |
location | string | |
roles | array of string | primary, billing, technical, important, decision_maker, meeting_invitee. |
notes | string | Align notes. |
source | string | |
psa_id | string | The contact's id in the PSA (text, as psa_id on clients). |
itflow_contact_id | integer | Older name for psa_id, kept for existing integrations. |
archived | boolean | |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/contacts/<id>Devices
/api/v1/devicesdevices:readList devices with lifecycle status
| Parameter | Type | |
|---|---|---|
client_id | integer | Only this client. |
status | string | Lifecycle status: replace, os_eos, plan, deferred, os_soon, warranty_expired, warranty_soon, ok, excluded, virtual. |
attention | boolean | Only devices that need attention (true) or don't (false). |
type | string | Device type, e.g. Server, Laptop. |
class | string | Category: desktop, laptop, server, network, printer, storage, power, other. |
virtual | boolean | Only virtual (true) or physical (false). |
search | string | Name, serial, model or last user contains. |
updated_since | string | Only items changed since this date/time (ISO 8601). Use it to sync incrementally. |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Device
A device with its computed lifecycle.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
client_name | string | |
name | string | |
type | string | e.g. Server, Hypervisor host, Laptop. |
category | string | Lifecycle category: desktop, laptop, server, network, printer, storage, power, display (2.25.0), other. |
is_virtual | boolean | |
source | string | ninja (NinjaOne), another RMM's key, the PSA's key (e.g. itflow) or manual. |
rmm | object | For RMM devices: provider (e.g. ninjaone), device_id, organization_id. null otherwise. |
manufacturer | string | |
model | string | |
serial | string | |
asset_tag | string | The client's own asset tag (2.21.0), or null. |
ip_address | string | |
location | string | |
last_user | string | |
last_seen | date-time | |
os | object | name, build, support_ends. |
lifecycle | object | status, status_label, health (ok/warn/bad/muted), flags, in_service_date, in_service_source, in_service_estimated, age_years, lifespan_years, end_of_life, replace_by, planned_replacement {quarter, label, note, deferred}, replacement_cost, excluded, project {id, title, status, target_quarter, psa_ticket_id}: the project replacing it (2.1; its devices leave the automatic plan, replace_by null). |
warranty | object | end, source. |
overrides | object | Values set in Align (null = using the synced value or policy default). |
psa_asset_id | string | The linked PSA asset (text, as psa_id on clients). |
itflow_asset_id | integer | Older name for psa_asset_id, kept for existing integrations. |
ninja_device_id | integer | NinjaOne devices only: same as rmm.device_id. Older field, kept for existing integrations. |
synced_at | date-time | |
url | string | |
psa_sync | object | After PATCH only: status (ok, off, queued, error) and message. |
itflow_sync | object | Older name for psa_sync, kept for existing integrations. |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/devices/api/v1/devices/{id}devices:readGet a device
Response: Device
A device with its computed lifecycle.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
client_name | string | |
name | string | |
type | string | e.g. Server, Hypervisor host, Laptop. |
category | string | Lifecycle category: desktop, laptop, server, network, printer, storage, power, display (2.25.0), other. |
is_virtual | boolean | |
source | string | ninja (NinjaOne), another RMM's key, the PSA's key (e.g. itflow) or manual. |
rmm | object | For RMM devices: provider (e.g. ninjaone), device_id, organization_id. null otherwise. |
manufacturer | string | |
model | string | |
serial | string | |
asset_tag | string | The client's own asset tag (2.21.0), or null. |
ip_address | string | |
location | string | |
last_user | string | |
last_seen | date-time | |
os | object | name, build, support_ends. |
lifecycle | object | status, status_label, health (ok/warn/bad/muted), flags, in_service_date, in_service_source, in_service_estimated, age_years, lifespan_years, end_of_life, replace_by, planned_replacement {quarter, label, note, deferred}, replacement_cost, excluded, project {id, title, status, target_quarter, psa_ticket_id}: the project replacing it (2.1; its devices leave the automatic plan, replace_by null). |
warranty | object | end, source. |
overrides | object | Values set in Align (null = using the synced value or policy default). |
psa_asset_id | string | The linked PSA asset (text, as psa_id on clients). |
itflow_asset_id | integer | Older name for psa_asset_id, kept for existing integrations. |
ninja_device_id | integer | NinjaOne devices only: same as rmm.device_id. Older field, kept for existing integrations. |
synced_at | date-time | |
url | string | |
psa_sync | object | After PATCH only: status (ok, off, queued, error) and message. |
itflow_sync | object | Older name for psa_sync, kept for existing integrations. |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/devices/<id>/api/v1/devices/{id}devices:writeChange a device's lifecycle details
Same as editing the device page: dates, lifespan and cost override the synced values and the policy defaults; the change goes to the PSA when two-way sync is on. Send null to clear an override.
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
purchase_date | date | Purchase / in-service date. Overrides what the RMM or PSA says. null = use the synced date. |
warranty_end | date | Warranty end. null = use the warranty lookup or PSA date. |
lifespan_years | integer | Lifespan for this device. null = the policy default for its type. From 1 to 29. |
replacement_cost | number | Replacement cost. null = the policy default for its type. From 0 to 10,000,000. |
replace_quarter | string | Plan the replacement in this quarter instead of at end of life (2027-Q2 or any date in it). null = follow end of life. |
replace_note | string | Why the replacement was moved (kept only with replace_quarter). Max 255 characters. |
excluded | boolean | Leave the device out of planning, budgets and reports. |
notes | string | Align notes. Max 5000 characters. |
asset_tag | string | The client's own asset tag (2.21.0). null = none. Not unique: the same tag on two devices is allowed. Max 64 characters. |
device_type | string | Device type (sets its lifecycle category). null = the type the RMM reports (not for devices added in Align or the PSA, whose type is their own). One of: Desktop, VDI / virtual desktop, Laptop, Server, Hypervisor host, Virtual server, Firewall, Router, Switch, Access point, Printer, NAS / Storage, UPS, Monitor, Phone, Camera / NVR, Other, Unassigned. |
Response: Device
A device with its computed lifecycle.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
client_name | string | |
name | string | |
type | string | e.g. Server, Hypervisor host, Laptop. |
category | string | Lifecycle category: desktop, laptop, server, network, printer, storage, power, display (2.25.0), other. |
is_virtual | boolean | |
source | string | ninja (NinjaOne), another RMM's key, the PSA's key (e.g. itflow) or manual. |
rmm | object | For RMM devices: provider (e.g. ninjaone), device_id, organization_id. null otherwise. |
manufacturer | string | |
model | string | |
serial | string | |
asset_tag | string | The client's own asset tag (2.21.0), or null. |
ip_address | string | |
location | string | |
last_user | string | |
last_seen | date-time | |
os | object | name, build, support_ends. |
lifecycle | object | status, status_label, health (ok/warn/bad/muted), flags, in_service_date, in_service_source, in_service_estimated, age_years, lifespan_years, end_of_life, replace_by, planned_replacement {quarter, label, note, deferred}, replacement_cost, excluded, project {id, title, status, target_quarter, psa_ticket_id}: the project replacing it (2.1; its devices leave the automatic plan, replace_by null). |
warranty | object | end, source. |
overrides | object | Values set in Align (null = using the synced value or policy default). |
psa_asset_id | string | The linked PSA asset (text, as psa_id on clients). |
itflow_asset_id | integer | Older name for psa_asset_id, kept for existing integrations. |
ninja_device_id | integer | NinjaOne devices only: same as rmm.device_id. Older field, kept for existing integrations. |
synced_at | date-time | |
url | string | |
psa_sync | object | After PATCH only: status (ok, off, queued, error) and message. |
itflow_sync | object | Older name for psa_sync, kept for existing integrations. |
curl -s -X PATCH -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"purchase_date": "2026-11-01", "warranty_end": "2026-11-01"}' \
https://align.example.com/api/v1/devices/<id>Projects
/api/v1/projectsprojects:readList projects
| Parameter | Type | |
|---|---|---|
client_id | integer | Only this client. |
status | string | proposed, approved, scheduled, done or declined. |
category | string | Project category. |
quarter | string | Planned in this quarter (2027-Q1 or any date in it). |
updated_since | string | Only items changed since this date/time (ISO 8601). Use it to sync incrementally. |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Project
A roadmap project.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
client_name | string | |
title | string | |
category | string | |
category_label | string | |
description | string | |
target_quarter | date | First day of the planned quarter; null = backlog. |
quarter_label | string | e.g. Q1 2027 or FY2027 Q3. |
cost | number | One-time. |
recurring_monthly | number | |
priority | string | critical, high, medium, low. |
status | string | proposed, approved, scheduled, done, declined. |
device_ids | array of integer | Devices this project replaces (made from Devices → Make projects); they leave the automatic replacement plan while the project isn't declined. |
psa_ticket_id | string | The project's QUOTE- ticket in the PSA, once someone pressed Ready to start (or asked for it when the project was made); null until then. |
started_at | date-time | When Ready to start was first pressed: the ticket was made, or (with no ticket possible, e.g. no PSA) the project was marked started; a ticket made later keeps this date. Null until then; projects whose ticket was made before 2.2.2 have none. |
decision | object | Who approved or declined it (e.g. in the client portal): by, at, comment, via_portal. |
alignment_standard_id | integer | The alignment standard this project fixes (made from a gap, 2.3.0); null otherwise. |
created_at | date-time | |
updated_at | date-time | |
url | string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/projects/api/v1/projectsprojects:writeCreate a project
| Parameter | Type | |
|---|---|---|
Idempotency-Key (header) | string | Send a unique value to make retries safe: the same key within 24 hours returns the first response instead of creating a duplicate. |
Body (JSON)
| Field | Type | |
|---|---|---|
client_id required | integer | Client the project belongs to (can't be changed later). |
title required | string | Project name. Max 255 characters. |
category | string | Category (default "project"). One of: hardware, infrastructure, security, compliance, software, cloud, backup, project, training. |
description | string | Plain-language description the client will read. Max 10000 characters. |
target_quarter | string | Planned quarter (2027-Q1 or any date in it; returned as the quarter's first day). null = backlog. |
cost | number | One-time cost. From 0 to 100,000,000. |
recurring_monthly | number | Added monthly cost once done. From 0 to 10,000,000. |
priority | string | Priority (default "medium"). One of: critical, high, medium, low. |
status | string | Status (default "proposed"). Approved and scheduled projects roll into the budget. One of: proposed, approved, scheduled, done, declined. |
alignment_standard_id | integer | The alignment standard this project fixes (GET /alignment/standards). |
Response: Project
A roadmap project.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
client_name | string | |
title | string | |
category | string | |
category_label | string | |
description | string | |
target_quarter | date | First day of the planned quarter; null = backlog. |
quarter_label | string | e.g. Q1 2027 or FY2027 Q3. |
cost | number | One-time. |
recurring_monthly | number | |
priority | string | critical, high, medium, low. |
status | string | proposed, approved, scheduled, done, declined. |
device_ids | array of integer | Devices this project replaces (made from Devices → Make projects); they leave the automatic replacement plan while the project isn't declined. |
psa_ticket_id | string | The project's QUOTE- ticket in the PSA, once someone pressed Ready to start (or asked for it when the project was made); null until then. |
started_at | date-time | When Ready to start was first pressed: the ticket was made, or (with no ticket possible, e.g. no PSA) the project was marked started; a ticket made later keeps this date. Null until then; projects whose ticket was made before 2.2.2 have none. |
decision | object | Who approved or declined it (e.g. in the client portal): by, at, comment, via_portal. |
alignment_standard_id | integer | The alignment standard this project fixes (made from a gap, 2.3.0); null otherwise. |
created_at | date-time | |
updated_at | date-time | |
url | string |
curl -s -X POST -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
-d '{"client_id": 12, "title": "text"}' \
https://align.example.com/api/v1/projects/api/v1/projects/{id}projects:readGet a project
Response: Project
A roadmap project.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
client_name | string | |
title | string | |
category | string | |
category_label | string | |
description | string | |
target_quarter | date | First day of the planned quarter; null = backlog. |
quarter_label | string | e.g. Q1 2027 or FY2027 Q3. |
cost | number | One-time. |
recurring_monthly | number | |
priority | string | critical, high, medium, low. |
status | string | proposed, approved, scheduled, done, declined. |
device_ids | array of integer | Devices this project replaces (made from Devices → Make projects); they leave the automatic replacement plan while the project isn't declined. |
psa_ticket_id | string | The project's QUOTE- ticket in the PSA, once someone pressed Ready to start (or asked for it when the project was made); null until then. |
started_at | date-time | When Ready to start was first pressed: the ticket was made, or (with no ticket possible, e.g. no PSA) the project was marked started; a ticket made later keeps this date. Null until then; projects whose ticket was made before 2.2.2 have none. |
decision | object | Who approved or declined it (e.g. in the client portal): by, at, comment, via_portal. |
alignment_standard_id | integer | The alignment standard this project fixes (made from a gap, 2.3.0); null otherwise. |
created_at | date-time | |
updated_at | date-time | |
url | string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/projects/<id>/api/v1/projects/{id}projects:writeChange a project
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
title | string | Project name. Max 255 characters. |
category | string | Category (default "project"). One of: hardware, infrastructure, security, compliance, software, cloud, backup, project, training. |
description | string | Plain-language description the client will read. Max 10000 characters. |
target_quarter | string | Planned quarter (2027-Q1 or any date in it; returned as the quarter's first day). null = backlog. |
cost | number | One-time cost. From 0 to 100,000,000. |
recurring_monthly | number | Added monthly cost once done. From 0 to 10,000,000. |
priority | string | Priority (default "medium"). One of: critical, high, medium, low. |
status | string | Status (default "proposed"). Approved and scheduled projects roll into the budget. One of: proposed, approved, scheduled, done, declined. |
Response: Project
A roadmap project.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
client_name | string | |
title | string | |
category | string | |
category_label | string | |
description | string | |
target_quarter | date | First day of the planned quarter; null = backlog. |
quarter_label | string | e.g. Q1 2027 or FY2027 Q3. |
cost | number | One-time. |
recurring_monthly | number | |
priority | string | critical, high, medium, low. |
status | string | proposed, approved, scheduled, done, declined. |
device_ids | array of integer | Devices this project replaces (made from Devices → Make projects); they leave the automatic replacement plan while the project isn't declined. |
psa_ticket_id | string | The project's QUOTE- ticket in the PSA, once someone pressed Ready to start (or asked for it when the project was made); null until then. |
started_at | date-time | When Ready to start was first pressed: the ticket was made, or (with no ticket possible, e.g. no PSA) the project was marked started; a ticket made later keeps this date. Null until then; projects whose ticket was made before 2.2.2 have none. |
decision | object | Who approved or declined it (e.g. in the client portal): by, at, comment, via_portal. |
alignment_standard_id | integer | The alignment standard this project fixes (made from a gap, 2.3.0); null otherwise. |
created_at | date-time | |
updated_at | date-time | |
url | string |
curl -s -X PATCH -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"title": "text", "category": "hardware"}' \
https://align.example.com/api/v1/projects/<id>/api/v1/projects/{id}projects:writeDelete a project
Returns 204 No Content.
curl -s -X DELETE -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/projects/<id>Budget
/api/v1/clients/{id}/budgetbudget:readGet a client's three-year technology budget
Everything the budget page shows: totals per year and quarter by category, recurring monthly run rate, each line (licensing, hardware, projects, managed services and your budget lines) and upcoming contract dates.
| Parameter | Type | |
|---|---|---|
year | integer | Which plan year the selected_year block shows: 0 (default), 1 or 2. |
Response: BudgetSummary
A client's three-year technology budget.
| Field | Type | |
|---|---|---|
client_id | integer | |
currency | string | |
recurring_monthly | number | Current recurring monthly run rate. |
selected_year | object | label, from, to, total, one_time, by_category. |
years | array of object | The three plan years, same shape. |
quarters | array of object | label, start, end, year_index, total, by_category. |
categories | object | Category key => label. |
lines | array of object | Every budget line: key, name, category, source (manual, licensing, hardware, projects, or the PSA's key for the managed-services estimate), budget_line_id, detail, monthly, one_time, tentative, by_quarter (12 values). |
contract_dates | array of object | date, kind, label, name, term, auto_renew, annual_value. |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/budget/api/v1/budget-linesbudget:readList budget lines
| Parameter | Type | |
|---|---|---|
client_id | integer | Only this client. |
category | string | Budget category. |
updated_since | string | Only items changed since this date/time (ISO 8601). Use it to sync incrementally. |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of BudgetLine
A budget line you added.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
name | string | |
category | string | |
vendor | string | |
amount | number | Per billing period. |
frequency | string | monthly, quarterly, annual, one_time. |
start_date | date | |
end_date | date | |
contract_term_months | integer | |
contract_end | date | |
notice_days | integer | |
renegotiate_date | date | |
auto_renew | boolean | |
notes | string | |
created_at | date-time | |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/budget-lines/api/v1/budget-linesbudget:writeCreate a budget line
| Parameter | Type | |
|---|---|---|
Idempotency-Key (header) | string | Send a unique value to make retries safe: the same key within 24 hours returns the first response instead of creating a duplicate. |
Body (JSON)
| Field | Type | |
|---|---|---|
client_id required | integer | Client (can't be changed later). |
name required | string | What the cost is for. Max 255 characters. |
category | string | Budget category (default "other"). A "managed" line replaces the managed-services estimate from PSA invoices. One of: managed, licensing, hardware, projects, connectivity, telecom, cloud, other. |
vendor | string | Max 190 characters. |
amount required | number | Amount per billing period. From 0 to 100,000,000. |
frequency | string | How often it's billed (default "monthly"). One of: monthly, quarterly, annual, one_time. |
start_date | date | First billing date (null = already running). |
end_date | date | Last billing date (null = ongoing). |
contract_term_months | integer | From 1 to 240. |
contract_end | date | Worked out from start_date + term when left out. |
notice_days | integer | From 0 to 730. |
renegotiate_date | date | Last day to give notice. Worked out from contract_end - notice_days when left out. |
auto_renew | boolean | |
notes | string | Max 5000 characters. |
Response: BudgetLine
A budget line you added.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
name | string | |
category | string | |
vendor | string | |
amount | number | Per billing period. |
frequency | string | monthly, quarterly, annual, one_time. |
start_date | date | |
end_date | date | |
contract_term_months | integer | |
contract_end | date | |
notice_days | integer | |
renegotiate_date | date | |
auto_renew | boolean | |
notes | string | |
created_at | date-time | |
updated_at | date-time |
curl -s -X POST -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
-d '{"client_id": 12, "name": "text", "amount": 1500}' \
https://align.example.com/api/v1/budget-lines/api/v1/budget-lines/{id}budget:readGet a budget line
Response: BudgetLine
A budget line you added.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
name | string | |
category | string | |
vendor | string | |
amount | number | Per billing period. |
frequency | string | monthly, quarterly, annual, one_time. |
start_date | date | |
end_date | date | |
contract_term_months | integer | |
contract_end | date | |
notice_days | integer | |
renegotiate_date | date | |
auto_renew | boolean | |
notes | string | |
created_at | date-time | |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/budget-lines/<id>/api/v1/budget-lines/{id}budget:writeChange a budget line
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
name | string | What the cost is for. Max 255 characters. |
category | string | Budget category (default "other"). A "managed" line replaces the managed-services estimate from PSA invoices. One of: managed, licensing, hardware, projects, connectivity, telecom, cloud, other. |
vendor | string | Max 190 characters. |
amount | number | Amount per billing period. From 0 to 100,000,000. |
frequency | string | How often it's billed (default "monthly"). One of: monthly, quarterly, annual, one_time. |
start_date | date | First billing date (null = already running). |
end_date | date | Last billing date (null = ongoing). |
contract_term_months | integer | From 1 to 240. |
contract_end | date | Worked out from start_date + term when left out. |
notice_days | integer | From 0 to 730. |
renegotiate_date | date | Last day to give notice. Worked out from contract_end - notice_days when left out. |
auto_renew | boolean | |
notes | string | Max 5000 characters. |
Response: BudgetLine
A budget line you added.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
name | string | |
category | string | |
vendor | string | |
amount | number | Per billing period. |
frequency | string | monthly, quarterly, annual, one_time. |
start_date | date | |
end_date | date | |
contract_term_months | integer | |
contract_end | date | |
notice_days | integer | |
renegotiate_date | date | |
auto_renew | boolean | |
notes | string | |
created_at | date-time | |
updated_at | date-time |
curl -s -X PATCH -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"name": "text", "category": "managed"}' \
https://align.example.com/api/v1/budget-lines/<id>/api/v1/budget-lines/{id}budget:writeDelete a budget line
Returns 204 No Content.
curl -s -X DELETE -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/budget-lines/<id>Licensing
/api/v1/licenseslicenses:readList licenses
| Parameter | Type | |
|---|---|---|
client_id | integer | Only this client. |
category | string | License category. |
unpriced | boolean | Only licenses without a price. |
renewing_within_days | integer | Expiry, contract end or renegotiate-by date within this many days. |
include_retired | boolean | Include retired licenses. |
updated_since | string | Only items changed since this date/time (ISO 8601). Use it to sync incrementally. |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of License
A software license or subscription.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
source | string | The PSA's key (e.g. itflow), m365 (from the client's Microsoft 365 tenant, 2.6.0), gws (from its Google Workspace, 2.6.3) or manual. |
psa_id | string | The license's id in the PSA (text, as psa_id on clients). |
itflow_software_id | integer | Older name for psa_id, kept for existing integrations. |
name | string | |
version | string | |
software_type | string | |
license_type | string | |
category | string | |
vendor | string | |
seats | integer | |
seats_used | integer | |
pricing | string | per_seat or flat. |
unit_price | number | |
price_source | string | Microsoft 365 licenses (2.6.0) and Google Workspace licenses (2.6.3): list (follows the price list) or custom (this license has its own price); null for others. |
billing_cycle | string | |
priced | boolean | |
cost_per_cycle | number | |
monthly | number | |
annual | number | |
purchase_date | date | |
expire_date | date | |
auto_renew | boolean | |
contract_start | date | |
contract_term_months | integer | |
contract_end | date | |
notice_days | integer | |
renegotiate_date | date | |
notes | string | Align notes. |
psa_notes | string | Notes from the PSA. |
itflow_notes | string | Older name for psa_notes, kept for existing integrations. |
retired | boolean | |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/licenses/api/v1/licenseslicenses:writeAdd a license
For licenses you track only in Align. Licenses from the PSA arrive with the sync.
| Parameter | Type | |
|---|---|---|
Idempotency-Key (header) | string | Send a unique value to make retries safe: the same key within 24 hours returns the first response instead of creating a duplicate. |
Body (JSON)
| Field | Type | |
|---|---|---|
client_id required | integer | Client (can't be changed later). |
name required | string | Product name (read-only for licenses synced from the PSA). Max 255 characters. |
version | string | Max 100 characters. |
software_type | string | Max 60 characters. |
license_type | string | One of: user, device, site, other. |
seats | integer | Seats purchased (read-only for licenses synced from the PSA). From 0 to 1,000,000. |
vendor | string | Max 190 characters. |
purchase_date | date | |
expire_date | date | Renewal / expiry date (read-only for licenses synced from the PSA). |
category | string | One of: productivity, security, backup, lob, infrastructure, communication, rmm, other. |
pricing | string | per_seat: unit_price × seats; flat: unit_price is the whole charge. One of: per_seat, flat. |
unit_price | number | Price per seat (or flat price) per billing period. null = not priced yet. From 0 to 10,000,000. |
billing_cycle | string | One of: monthly, quarterly, annual, one_time. |
seats_used | integer | From 0 to 1,000,000. |
auto_renew | boolean | |
contract_start | date | |
contract_term_months | integer | From 1 to 240. |
contract_end | date | Worked out from contract_start (or purchase_date) + term when left out. |
notice_days | integer | From 0 to 730. |
renegotiate_date | date | Worked out from contract_end - notice_days when left out. |
notes | string | Align notes. Max 5000 characters. |
Response: License
A software license or subscription.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
source | string | The PSA's key (e.g. itflow), m365 (from the client's Microsoft 365 tenant, 2.6.0), gws (from its Google Workspace, 2.6.3) or manual. |
psa_id | string | The license's id in the PSA (text, as psa_id on clients). |
itflow_software_id | integer | Older name for psa_id, kept for existing integrations. |
name | string | |
version | string | |
software_type | string | |
license_type | string | |
category | string | |
vendor | string | |
seats | integer | |
seats_used | integer | |
pricing | string | per_seat or flat. |
unit_price | number | |
price_source | string | Microsoft 365 licenses (2.6.0) and Google Workspace licenses (2.6.3): list (follows the price list) or custom (this license has its own price); null for others. |
billing_cycle | string | |
priced | boolean | |
cost_per_cycle | number | |
monthly | number | |
annual | number | |
purchase_date | date | |
expire_date | date | |
auto_renew | boolean | |
contract_start | date | |
contract_term_months | integer | |
contract_end | date | |
notice_days | integer | |
renegotiate_date | date | |
notes | string | Align notes. |
psa_notes | string | Notes from the PSA. |
itflow_notes | string | Older name for psa_notes, kept for existing integrations. |
retired | boolean | |
updated_at | date-time |
curl -s -X POST -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
-d '{"client_id": 12, "name": "text"}' \
https://align.example.com/api/v1/licenses/api/v1/licenses/{id}licenses:readGet a license
Response: License
A software license or subscription.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
source | string | The PSA's key (e.g. itflow), m365 (from the client's Microsoft 365 tenant, 2.6.0), gws (from its Google Workspace, 2.6.3) or manual. |
psa_id | string | The license's id in the PSA (text, as psa_id on clients). |
itflow_software_id | integer | Older name for psa_id, kept for existing integrations. |
name | string | |
version | string | |
software_type | string | |
license_type | string | |
category | string | |
vendor | string | |
seats | integer | |
seats_used | integer | |
pricing | string | per_seat or flat. |
unit_price | number | |
price_source | string | Microsoft 365 licenses (2.6.0) and Google Workspace licenses (2.6.3): list (follows the price list) or custom (this license has its own price); null for others. |
billing_cycle | string | |
priced | boolean | |
cost_per_cycle | number | |
monthly | number | |
annual | number | |
purchase_date | date | |
expire_date | date | |
auto_renew | boolean | |
contract_start | date | |
contract_term_months | integer | |
contract_end | date | |
notice_days | integer | |
renegotiate_date | date | |
notes | string | Align notes. |
psa_notes | string | Notes from the PSA. |
itflow_notes | string | Older name for psa_notes, kept for existing integrations. |
retired | boolean | |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/licenses/<id>/api/v1/licenses/{id}licenses:writeChange a license
For licenses synced from the PSA, name, version, type, seats, vendor and dates are managed there and refused here.
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
name | string | Product name (read-only for licenses synced from the PSA). Max 255 characters. |
version | string | Max 100 characters. |
software_type | string | Max 60 characters. |
license_type | string | One of: user, device, site, other. |
seats | integer | Seats purchased (read-only for licenses synced from the PSA). From 0 to 1,000,000. |
vendor | string | Max 190 characters. |
purchase_date | date | |
expire_date | date | Renewal / expiry date (read-only for licenses synced from the PSA). |
category | string | One of: productivity, security, backup, lob, infrastructure, communication, rmm, other. |
pricing | string | per_seat: unit_price × seats; flat: unit_price is the whole charge. One of: per_seat, flat. |
unit_price | number | Price per seat (or flat price) per billing period. null = not priced yet. From 0 to 10,000,000. |
billing_cycle | string | One of: monthly, quarterly, annual, one_time. |
seats_used | integer | From 0 to 1,000,000. |
auto_renew | boolean | |
contract_start | date | |
contract_term_months | integer | From 1 to 240. |
contract_end | date | Worked out from contract_start (or purchase_date) + term when left out. |
notice_days | integer | From 0 to 730. |
renegotiate_date | date | Worked out from contract_end - notice_days when left out. |
notes | string | Align notes. Max 5000 characters. |
retired | boolean | Retire (true) or restore (false). Retired licenses don't count toward totals. |
Response: License
A software license or subscription.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
source | string | The PSA's key (e.g. itflow), m365 (from the client's Microsoft 365 tenant, 2.6.0), gws (from its Google Workspace, 2.6.3) or manual. |
psa_id | string | The license's id in the PSA (text, as psa_id on clients). |
itflow_software_id | integer | Older name for psa_id, kept for existing integrations. |
name | string | |
version | string | |
software_type | string | |
license_type | string | |
category | string | |
vendor | string | |
seats | integer | |
seats_used | integer | |
pricing | string | per_seat or flat. |
unit_price | number | |
price_source | string | Microsoft 365 licenses (2.6.0) and Google Workspace licenses (2.6.3): list (follows the price list) or custom (this license has its own price); null for others. |
billing_cycle | string | |
priced | boolean | |
cost_per_cycle | number | |
monthly | number | |
annual | number | |
purchase_date | date | |
expire_date | date | |
auto_renew | boolean | |
contract_start | date | |
contract_term_months | integer | |
contract_end | date | |
notice_days | integer | |
renegotiate_date | date | |
notes | string | Align notes. |
psa_notes | string | Notes from the PSA. |
itflow_notes | string | Older name for psa_notes, kept for existing integrations. |
retired | boolean | |
updated_at | date-time |
curl -s -X PATCH -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"name": "text", "version": "text"}' \
https://align.example.com/api/v1/licenses/<id>/api/v1/licenses/{id}licenses:writeDelete a license you added
Returns 204 No Content.
curl -s -X DELETE -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/licenses/<id>Vendors
/api/v1/vendorsvendors:readList client vendors
Each client's vendors as its Vendors page shows them: a field left blank on the vendor takes its template's value (from_template lists which).
| Parameter | Type | |
|---|---|---|
client_id | integer | Only this client. |
category | string | Vendor category (its own, else its template's). |
include_retired | boolean | Include retired vendors. |
updated_since | string | Only items changed since this date/time (ISO 8601). Use it to sync incrementally. |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Vendor
A client's vendor (2.10.0), as its Vendors page shows it.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
client_name | string | |
source | string | The PSA's key (e.g. itflow) for vendors synced from it, else manual. |
psa_id | string | The vendor's id in the PSA. |
template_id | integer | The vendor template it uses, or null. |
template_name | string | |
name | string | |
category | string | internet, phone, registrar, hosting, software, lob, security, print, hardware or other. |
description | string | From the PSA. |
account_number | string | |
contact_name | string | |
support_phone | string | |
support_email | string | |
website | string | |
hours | string | |
sla | string | |
services | string | What the client has from this vendor. |
notes | string | Align notes. |
psa_notes | string | Notes from the PSA (synced vendors). |
from_template | array of string | The fields shown from the template (blank on the vendor itself). |
retired | boolean | |
retired_reason | string | psa (archived or deleted in the PSA) or align. |
created_at | date-time | |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/vendors/api/v1/vendors/{id}vendors:readGet a client vendor
Response: Vendor
A client's vendor (2.10.0), as its Vendors page shows it.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
client_name | string | |
source | string | The PSA's key (e.g. itflow) for vendors synced from it, else manual. |
psa_id | string | The vendor's id in the PSA. |
template_id | integer | The vendor template it uses, or null. |
template_name | string | |
name | string | |
category | string | internet, phone, registrar, hosting, software, lob, security, print, hardware or other. |
description | string | From the PSA. |
account_number | string | |
contact_name | string | |
support_phone | string | |
support_email | string | |
website | string | |
hours | string | |
sla | string | |
services | string | What the client has from this vendor. |
notes | string | Align notes. |
psa_notes | string | Notes from the PSA (synced vendors). |
from_template | array of string | The fields shown from the template (blank on the vendor itself). |
retired | boolean | |
retired_reason | string | psa (archived or deleted in the PSA) or align. |
created_at | date-time | |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/vendors/<id>/api/v1/vendor-templatesvendors:readList vendor templates
The shared vendor details entered once, with how many clients use each. Not paginated.
Response: VendorTemplate
A vendor template (2.10.0): details shared by every client that uses it.
| Field | Type | |
|---|---|---|
id | integer | |
name | string | |
category | string | |
website | string | |
support_phone | string | |
support_email | string | |
hours | string | |
sla | string | |
notes | string | |
psa_template_id | string | The PSA's vendor template it stands for, or null. |
clients | integer | Clients with an active vendor made from it. |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/vendor-templatesMeetings
/api/v1/meetingsmeetings:readList meetings
| Parameter | Type | |
|---|---|---|
client_id | integer | Only this client. |
from | string | Starting on or after (date or date-time). |
to | string | Starting on or before. |
status | string | scheduled, completed or cancelled. |
type | string | Meeting type. |
updated_since | string | Only items changed since this date/time (ISO 8601). Use it to sync incrementally. |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Meeting
A meeting.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | null = internal. |
title | string | |
type | string | |
type_label | string | |
status | string | scheduled, completed, cancelled. |
starts_at | date-time | |
ends_at | date-time | |
duration_minutes | integer | |
location | string | |
video_url | string | |
attendees | array of object | email, name. |
agenda | string | |
notes | string | |
owner | object | id, name. |
series_id | integer | |
invitations_sent_at | date-time | |
created_at | date-time | |
updated_at | date-time | |
url | string | |
invitations | string | After POST/PATCH with send_invites: what happened to the invitations. |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/meetings/api/v1/meetingsmeetings:writeSchedule a meeting
| Parameter | Type | |
|---|---|---|
Idempotency-Key (header) | string | Send a unique value to make retries safe: the same key within 24 hours returns the first response instead of creating a duplicate. |
Body (JSON)
| Field | Type | |
|---|---|---|
client_id | integer | Client (null = internal meeting; needs a key for all clients). |
title | string | Title (default: the meeting type's name). Max 255 characters. |
type | string | Meeting type (default "other"). One of: abr, qbr, tbr, strategy, onboarding, compliance, project, internal, other. |
starts_at required | date-time | Start, ISO 8601 (e.g. 2026-10-14T09:00:00-07:00). Without an offset the server's time zone is used. |
duration_minutes | integer | Length (default from Settings → Planning). From 15 to 600. |
location | string | Max 255 characters. |
video_url | uri | Teams / Meet / Zoom link. |
attendees | array of string | List of "email" or "Name |
agenda | string | Max 20000 characters. |
owner_id | integer | Staff user (tech or admin) who owns / organizes it (default: the key's creator). Invitations can go out from this person's mailbox, so only keys for all clients may set it. |
send_invites | boolean | Email calendar invitations (or updates) to the attendees. Default false. Needs a key for all clients. |
Response: Meeting
A meeting.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | null = internal. |
title | string | |
type | string | |
type_label | string | |
status | string | scheduled, completed, cancelled. |
starts_at | date-time | |
ends_at | date-time | |
duration_minutes | integer | |
location | string | |
video_url | string | |
attendees | array of object | email, name. |
agenda | string | |
notes | string | |
owner | object | id, name. |
series_id | integer | |
invitations_sent_at | date-time | |
created_at | date-time | |
updated_at | date-time | |
url | string | |
invitations | string | After POST/PATCH with send_invites: what happened to the invitations. |
curl -s -X POST -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
-d '{"starts_at": "2026-11-04T09:00:00-08:00"}' \
https://align.example.com/api/v1/meetings/api/v1/meetings/{id}meetings:readGet a meeting
Response: Meeting
A meeting.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | null = internal. |
title | string | |
type | string | |
type_label | string | |
status | string | scheduled, completed, cancelled. |
starts_at | date-time | |
ends_at | date-time | |
duration_minutes | integer | |
location | string | |
video_url | string | |
attendees | array of object | email, name. |
agenda | string | |
notes | string | |
owner | object | id, name. |
series_id | integer | |
invitations_sent_at | date-time | |
created_at | date-time | |
updated_at | date-time | |
url | string | |
invitations | string | After POST/PATCH with send_invites: what happened to the invitations. |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/meetings/<id>/api/v1/meetings/{id}meetings:writeChange, complete or cancel a meeting
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
client_id | integer | Client (null = internal meeting; needs a key for all clients). |
title | string | Title (default: the meeting type's name). Max 255 characters. |
type | string | Meeting type (default "other"). One of: abr, qbr, tbr, strategy, onboarding, compliance, project, internal, other. |
starts_at | date-time | Start, ISO 8601 (e.g. 2026-10-14T09:00:00-07:00). Without an offset the server's time zone is used. |
duration_minutes | integer | Length (default from Settings → Planning). From 15 to 600. |
location | string | Max 255 characters. |
video_url | uri | Teams / Meet / Zoom link. |
attendees | array of string | List of "email" or "Name |
agenda | string | Max 20000 characters. |
owner_id | integer | Staff user (tech or admin) who owns / organizes it (default: the key's creator). Invitations can go out from this person's mailbox, so only keys for all clients may set it. |
status | string | Mark completed or cancelled (cancelling sends cancellations if invitations went out), or scheduled to reopen. One of: scheduled, completed, cancelled. |
notes | string | Meeting notes. Max 50000 characters. |
send_invites | boolean | Email calendar invitations (or updates) to the attendees. Default false. Needs a key for all clients. |
Response: Meeting
A meeting.
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | null = internal. |
title | string | |
type | string | |
type_label | string | |
status | string | scheduled, completed, cancelled. |
starts_at | date-time | |
ends_at | date-time | |
duration_minutes | integer | |
location | string | |
video_url | string | |
attendees | array of object | email, name. |
agenda | string | |
notes | string | |
owner | object | id, name. |
series_id | integer | |
invitations_sent_at | date-time | |
created_at | date-time | |
updated_at | date-time | |
url | string | |
invitations | string | After POST/PATCH with send_invites: what happened to the invitations. |
curl -s -X PATCH -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"client_id": 12, "title": "text"}' \
https://align.example.com/api/v1/meetings/<id>/api/v1/meetings/{id}meetings:writeDelete a meeting
Attendees get a cancellation first if invitations had gone out.
Returns 204 No Content.
curl -s -X DELETE -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/meetings/<id>Compliance
/api/v1/compliance/frameworkscompliance:readList frameworks
| Parameter | Type | |
|---|---|---|
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Framework
A compliance framework.
| Field | Type | |
|---|---|---|
id | integer | |
slug | string | |
name | string | |
description | string | |
built_in | boolean | |
controls | integer |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/compliance/frameworks/api/v1/clients/{id}/compliancecompliance:readList a client's frameworks with scores
| Parameter | Type | |
|---|---|---|
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Assessment
A framework assigned to a client, with its score.
| Field | Type | |
|---|---|---|
client_id | integer | |
framework_id | integer | |
framework | string | |
slug | string | |
assigned_at | date-time | |
last_reviewed | date | |
next_review | date | |
score | object | percent (partial counts half), met, partial, not_met, not_assessed, applicable, assessed_percent. |
url | string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/compliance/api/v1/clients/{id}/compliancecompliance:writeAssign a framework to a client
| Parameter | Type | |
|---|---|---|
Idempotency-Key (header) | string | Send a unique value to make retries safe: the same key within 24 hours returns the first response instead of creating a duplicate. |
Body (JSON)
| Field | Type | |
|---|---|---|
framework_id required | integer | Framework to assign. |
next_review | date | Next review (default one year). |
Response: Assessment
A framework assigned to a client, with its score.
| Field | Type | |
|---|---|---|
client_id | integer | |
framework_id | integer | |
framework | string | |
slug | string | |
assigned_at | date-time | |
last_reviewed | date | |
next_review | date | |
score | object | percent (partial counts half), met, partial, not_met, not_assessed, applicable, assessed_percent. |
url | string |
curl -s -X POST -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
-d '{"framework_id": 1}' \
https://align.example.com/api/v1/clients/<id>/compliance/api/v1/clients/{id}/compliance/{framework}compliance:writeSet review dates
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
next_review | date | |
last_reviewed | date |
Response: Assessment
A framework assigned to a client, with its score.
| Field | Type | |
|---|---|---|
client_id | integer | |
framework_id | integer | |
framework | string | |
slug | string | |
assigned_at | date-time | |
last_reviewed | date | |
next_review | date | |
score | object | percent (partial counts half), met, partial, not_met, not_assessed, applicable, assessed_percent. |
url | string |
curl -s -X PATCH -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"next_review": "2026-11-01", "last_reviewed": "2026-11-01"}' \
https://align.example.com/api/v1/clients/<id>/compliance/<framework>/api/v1/clients/{id}/compliance/{framework}compliance:writeRemove a framework from a client
Answers are kept and come back if the framework is assigned again.
Returns 204 No Content.
curl -s -X DELETE -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/compliance/<framework>/api/v1/clients/{id}/compliance/{framework}/controlscompliance:readList controls with the client's status
| Parameter | Type | |
|---|---|---|
status | string | not_assessed, met, partial, not_met or na. |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Control
A control and the client's status for it.
| Field | Type | |
|---|---|---|
id | integer | |
ref | string | |
section | string | |
title | string | |
guidance | string | What "met" looks like and the evidence to collect. |
automatic_check | string | Check Align runs from its own data, if any. |
crosswalk_tags | array of string | |
status | string | |
notes | string | |
evidence | string | |
owner | string | |
due_date | date | |
document_id | integer | |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/compliance/<framework>/controls/api/v1/clients/{id}/compliance/{framework}/controlscompliance:writeUpdate many controls
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
controls | array of object | Up to 500 items: {"id": |
Response: BulkResult
Result of a bulk update.
| Field | Type | |
|---|---|---|
updated | integer | |
unchanged | integer | |
assessment | object | The framework's score afterwards. |
curl -s -X PATCH -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"controls": [{"id": 101, "status": "met"}]}' \
https://align.example.com/api/v1/clients/<id>/compliance/<framework>/controls/api/v1/clients/{id}/compliance/{framework}/controls/{control}compliance:writeUpdate one control
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
status | string | Assessment result. One of: not_assessed, met, partial, not_met, na. |
notes | string | Max 5000 characters. |
evidence | string | Where the evidence is (link, file name, ticket). Max 2000 characters. |
owner | string | Who is responsible. Max 190 characters. |
due_date | date | |
document_id | integer | Linked Align document (must belong to the client). |
Response: Control
A control and the client's status for it.
| Field | Type | |
|---|---|---|
id | integer | |
ref | string | |
section | string | |
title | string | |
guidance | string | What "met" looks like and the evidence to collect. |
automatic_check | string | Check Align runs from its own data, if any. |
crosswalk_tags | array of string | |
status | string | |
notes | string | |
evidence | string | |
owner | string | |
due_date | date | |
document_id | integer | |
updated_at | date-time |
curl -s -X PATCH -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"status": "not_assessed", "notes": "text"}' \
https://align.example.com/api/v1/clients/<id>/compliance/<framework>/controls/<control>Health
/api/v1/clients/{id}/healthhealth:readGet a client's health score
One score from 0 to 100 made from lifecycle, backups, compliance, service levels and alignment, each scored 0 to 100 and weighted as set in Settings → Planning & lifecycle. An area with no data is left out. Each area's details (what pulls it down) are included only when the key can read that area; otherwise details is null. Worked out now, and stored as today's entry in the history.
Response: Health
A client's health score (2.5.0).
| Field | Type | |
|---|---|---|
client_id | integer | |
score | integer | 0-100; null when no area has data. |
band | string | Healthy, Needs attention, At risk or No score. |
areas_counted | integer | Areas with data and a weight above 0. |
areas_weighted | integer | Areas with a weight above 0. |
bands | object | healthy_from, needs_attention_from (the settings in use). |
areas | array of object | key (lifecycle, backups, compliance, service, alignment, security (2.6.1)), label, score (null = no data), weight, counted, details [{text, tone}] (null when the key can't read that area). |
weakest | object | key, score of the lowest counted area; null when none. |
since_last_review | object | date, score then, change, label (with meetings:read) of the newest completed business review; null when there is none or no score from then. |
url | string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/health/api/v1/clients/{id}/health/historyhealth:readGet a client's health history
One entry per day that was recorded (once a day, and whenever the client is opened), newest first. Scores are worked out with the weights in use now.
| Parameter | Type | |
|---|---|---|
days | integer | How many days back, 1-1100 (default 90). |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of HealthDay
A client's health on one day (2.5.0).
| Field | Type | |
|---|---|---|
date | date | |
score | integer | Null when no area had data. |
band | string | |
areas | object | lifecycle, backups, compliance, service, alignment, security (2.6.1): each 0-100 or null. |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/health/historyAlignment
/api/v1/alignment/standardsalignment:readList the standards
The library alignment reviews measure clients against. Admins edit it in the web app (Libraries → Alignment standards).
| Parameter | Type | |
|---|---|---|
include_inactive | boolean | Also standards switched off (kept for old reviews). |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Standard
A standard in the alignment library (2.3.0).
| Field | Type | |
|---|---|---|
id | integer | |
category | string | |
section | string | Optional heading above the category. |
title | string | |
why | string | Why it matters, in the client's words. |
how | string | How to check it (staff notes). |
priority | string | critical, high, medium, low. |
weight | integer | How much it counts in the score: 4, 3, 2 or 1. |
auto_check | string | os_supported, hw_lifecycle, warranty, stale, backups, or (2.6.1) a Microsoft 365 check: m365_secure_score, m365_mfa_users, m365_mfa_admins, m365_mfa_enforced, m365_legacy_blocked, m365_admin_count, m365_stale; or (2.6.3) a Google Workspace check: gws_mfa_users, gws_mfa_admins, gws_mfa_enforced, gws_admin_count, gws_stale, gws_external_sharing, gws_third_party_apps, gws_less_secure_apps; or an email authentication check: email_spf, email_dkim, email_dmarc; or (2.7.0) huntress_agents, huntress_incidents, huntress_av, huntress_identities, huntress_ports, sat_training, sat_phishing; null = answered by hand. |
tags | array of string | Compliance tags: answers are shared with compliance controls that have the same tags. |
suggested_fix | object | title, category, cost: what Make project fills in. |
active | boolean | false = switched off (kept for old reviews). |
updated_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/alignment/standards/api/v1/clients/{id}/alignmentalignment:readGet a client's alignment
The latest finished review's score and band, the change since the review before, the gaps (most important first, each with its roadmap project if one was made and the compliance controls it helps with) and the open draft.
Response: Alignment
A client's alignment with the standards (2.3.0).
| Field | Type | |
|---|---|---|
client_id | integer | |
score | integer | Percent from the latest finished review; null = never reviewed (or nothing that applies). |
band | string | On track (80+), Needs attention (60-79), At risk (under 60), Not reviewed or No score. |
reviewed_at | date-time | |
reviewed_by | string | |
review_id | integer | |
counts | object | aligned, misaligned, not_applicable, unanswered. |
change | object | points since the review before, since (its date); null with fewer than two reviews. |
gaps | array of object | standard_id, title, priority, category, note, why, helps_with (compliance controls), project {id, title, status, target_quarter} or null. Most important first. |
not_applicable | array of object | standard_id, title, note. |
draft | object | id, started_at of the open draft; null when none. |
url | string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/alignment/api/v1/clients/{id}/alignment/reviewsalignment:readList a client's reviews
| Parameter | Type | |
|---|---|---|
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of AlignmentReview
An alignment review (2.3.0).
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
status | string | draft or done. |
started_at | date-time | |
started_by | string | |
finished_at | date-time | |
finished_by | string | |
score | integer | Stored when finished. |
band | string | |
counts | object | aligned, misaligned, not_applicable, unanswered. |
score_so_far | integer | Drafts, with answers: the score if it were finished now. |
answers | array of object | Single review only: standard_id, category, title, priority, auto_check, answer (aligned, misaligned, na or null), note, updated_at. A draft lists every active standard. |
url | string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/alignment/reviews/api/v1/clients/{id}/alignment/reviewsalignment:writeStart a review
Starts from the last finished review's answers. If a draft is already open it is returned instead (200). Send an empty body.
Response: AlignmentReview
An alignment review (2.3.0).
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
status | string | draft or done. |
started_at | date-time | |
started_by | string | |
finished_at | date-time | |
finished_by | string | |
score | integer | Stored when finished. |
band | string | |
counts | object | aligned, misaligned, not_applicable, unanswered. |
score_so_far | integer | Drafts, with answers: the score if it were finished now. |
answers | array of object | Single review only: standard_id, category, title, priority, auto_check, answer (aligned, misaligned, na or null), note, updated_at. A draft lists every active standard. |
url | string |
curl -s -X POST -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/alignment/reviews/api/v1/clients/{id}/alignment/reviews/{review}alignment:readGet a review with its answers
Response: AlignmentReview
An alignment review (2.3.0).
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
status | string | draft or done. |
started_at | date-time | |
started_by | string | |
finished_at | date-time | |
finished_by | string | |
score | integer | Stored when finished. |
band | string | |
counts | object | aligned, misaligned, not_applicable, unanswered. |
score_so_far | integer | Drafts, with answers: the score if it were finished now. |
answers | array of object | Single review only: standard_id, category, title, priority, auto_check, answer (aligned, misaligned, na or null), note, updated_at. A draft lists every active standard. |
url | string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/alignment/reviews/<review>/api/v1/clients/{id}/alignment/reviews/{review}alignment:writeDiscard a draft
Finished reviews are kept: 409.
Returns 204 No Content.
curl -s -X DELETE -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/alignment/reviews/<review>/api/v1/clients/{id}/alignment/reviews/{review}/answersalignment:writeAnswer standards in a draft
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
answers | array of object | Up to 500 items: {"standard_id": 12, "answer": "aligned", "note": "..."}. answer is aligned, misaligned or na; a field left out stays as it is. All or nothing; 409 when the review is finished. |
Response: AlignmentAnswersResult
Result of answering standards.
| Field | Type | |
|---|---|---|
updated | integer | |
unchanged | integer | |
review | object | The review afterwards (without answers). |
curl -s -X PATCH -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"answers": [{"id": 101, "status": "met"}]}' \
https://align.example.com/api/v1/clients/<id>/alignment/reviews/<review>/answers/api/v1/clients/{id}/alignment/reviews/{review}/finishalignment:writeFinish a draft
Stores the score (weighted by priority; N/A and unanswered standards left out). 409 when it is already finished.
Response: AlignmentReview
An alignment review (2.3.0).
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
status | string | draft or done. |
started_at | date-time | |
started_by | string | |
finished_at | date-time | |
finished_by | string | |
score | integer | Stored when finished. |
band | string | |
counts | object | aligned, misaligned, not_applicable, unanswered. |
score_so_far | integer | Drafts, with answers: the score if it were finished now. |
answers | array of object | Single review only: standard_id, category, title, priority, auto_check, answer (aligned, misaligned, na or null), note, updated_at. A draft lists every active standard. |
url | string |
curl -s -X POST -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/alignment/reviews/<review>/finishBackups
/api/v1/backupsbackups:readBackup health for every client
| Parameter | Type | |
|---|---|---|
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of BackupSummary
Backup health for one client.
| Field | Type | |
|---|---|---|
client_id | integer | |
client_name | string | |
health | string | ok, warn, bad or muted. |
jobs | integer | |
failed_jobs | integer | |
jobs_with_warnings | integer | |
protected_machines | integer | |
overdue | integer | |
success_rate_30d | integer |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/backups/api/v1/clients/{id}/backupsbackups:readGet a client's backups
Stats, 30-day history, jobs (with the backup product's messages), protected machines, Microsoft 365 and servers with no backup. Includes machines backed up on your own server.
Response: ClientBackups
A client's backups.
| Field | Type | |
|---|---|---|
client_id | integer | |
health | string | |
synced_at | date-time | |
stale_after_hours | integer | |
stats | object | |
history_30d | array of object | date, result (success, warning, failed, none). |
jobs | array of object | uid, name, kind, status, label, health, enabled, last_run, duration_seconds, message, target, size_bytes, hosted, shared_with_other_clients. |
machines | array of object | uid, name, kind, status, health, newest_restore_point, restore_points, backup_bytes, device_id, hosted, not_required. |
servers_without_backup | array of object | device_id, name, type. |
microsoft_365 | object | health, protected_objects, users, overdue, newest_restore_point, by_type, and objects: one per user, group, team or site (uid, name, type, health, newest_restore_point, restore_points, days_with_backup, counting_since, repositories, not_required, no_longer_backed_up: no new backup for longer than the "no longer backed up" days, old backups kept, health "retired", not counted). A mailbox kept in more than one repository is one object; days_with_backup counts each day with a restore point once, from counting_since. |
url | string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/backups/api/v1/clients/{id}/backup-exemptionsbackups:readList items marked "backup not required"
| Parameter | Type | |
|---|---|---|
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of Exemption
An item marked "backup not required".
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
kind | string | device, workload or m365. |
device_id | integer | |
item_uid | string | |
name | string | |
reason | string | |
created_at | date-time |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/backup-exemptions/api/v1/clients/{id}/backup-exemptionsbackups:writeMark an item "backup not required"
| Parameter | Type | |
|---|---|---|
Idempotency-Key (header) | string | Send a unique value to make retries safe: the same key within 24 hours returns the first response instead of creating a duplicate. |
Body (JSON)
| Field | Type | |
|---|---|---|
kind required | string | One of: device, workload, m365. |
device_id | integer | For kind=device. |
item_uid | string | For kind=workload or m365. |
reason required | string | Max 255 characters. |
Response: Exemption
An item marked "backup not required".
| Field | Type | |
|---|---|---|
id | integer | |
client_id | integer | |
kind | string | device, workload or m365. |
device_id | integer | |
item_uid | string | |
name | string | |
reason | string | |
created_at | date-time |
curl -s -X POST -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
-d '{"kind": "device", "reason": "text"}' \
https://align.example.com/api/v1/clients/<id>/backup-exemptions/api/v1/clients/{id}/backup-exemptions/{exemption}backups:writeRemove a "not required" mark
Returns 204 No Content.
curl -s -X DELETE -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/backup-exemptions/<exemption>/api/v1/backups/hostedbackups:readMachines and jobs on your own backup server
meta.jobs lists the jobs. Needs a key for all clients.
| Parameter | Type | |
|---|---|---|
show | string | unmatched, sorted, ours or all (default). |
page | integer | Page number (default 1). |
per_page | integer | Items per page, 1-200 (default 50). |
Response: a list of HostedMachine
A machine on your own backup server.
| Field | Type | |
|---|---|---|
uid | string | |
name | string | |
kind | string | vm or computer. |
newest_restore_point | date-time | |
client_id | integer | |
client_name | string | |
matched_by | string | device_name, job, manual or company. |
state | string | sorted, ours or unmatched. |
assignment | string | "auto", "ours" or a client id set by hand. |
device_id | integer | |
job_uids | array of string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/backups/hosted/api/v1/backups/hosted/machines/{uid}backups:writeAssign a hosted machine
uid from GET /backups/hosted, URL-encoded (vm:abc -> vm%3Aabc). Needs a key for all clients.
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
assign | string | A client id (number), "ours" or "auto". |
Response: HostedAssignment
Result of assigning a hosted machine or job.
| Field | Type | |
|---|---|---|
uid | string | |
name | string | |
client_id | integer | Machines. |
client_ids | array of integer | Jobs. |
state | string | Machines. |
machines | integer | Jobs. |
curl -s -X PUT -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"assign": "text"}' \
https://align.example.com/api/v1/backups/hosted/machines/<uid>/api/v1/backups/hosted/jobs/{uid}backups:writeAssign a hosted job (and its machines)
Needs a key for all clients.
Body (JSON): send only what changes
| Field | Type | |
|---|---|---|
assign | string | A client id (number), "ours" or "auto". |
Response: HostedAssignment
Result of assigning a hosted machine or job.
| Field | Type | |
|---|---|---|
uid | string | |
name | string | |
client_id | integer | Machines. |
client_ids | array of integer | Jobs. |
state | string | Machines. |
machines | integer | Jobs. |
curl -s -X PUT -H "Authorization: Bearer $ALIGN_KEY" -H "Content-Type: application/json" \
-d '{"assign": "text"}' \
https://align.example.com/api/v1/backups/hosted/jobs/<uid>Service levels
/api/v1/clients/{id}/service-levelsservice:readGet a client's SLA results
| Parameter | Type | |
|---|---|---|
period | string | Days (30, 90, 180, 365) or a named period as on the Service levels page. Default 90. |
missed_limit | integer | How many missed tickets to list (max 100, default 25). |
Response: ServiceLevels
SLA results for a period.
| Field | Type | |
|---|---|---|
client_id | integer | |
period | string | |
label | string | |
goal_pct | number | |
has_sla | boolean | |
synced_at | date-time | Last ticket sync. |
stats | object | tickets, responded_on_time_pct, resolved_on_time_pct, response_met/missed, resolution_met/missed, avg_first_response_minutes. |
previous_period | object | Same shape. |
open | object | total, past_target, close_to_target. |
monthly | array of object | Last 12 months, oldest first: month (YYYY-MM) plus the stats fields. |
by_priority | array of object | |
missed_tickets | array of object | number, opened, priority, subject, missed_response, missed_resolution. |
url | string |
curl -s -H "Authorization: Bearer $ALIGN_KEY" \
https://align.example.com/api/v1/clients/<id>/service-levels
Suggest