API Changelog
Changes to the Align Public API v1, its webhooks, and the MCP server, newest first. Each change is marked Added, Changed, Fixed or Removed. Read the Changed and Removed items carefully: they can affect an existing integration.
Convention for contributors: add a new ## YYYY-MM-DD section at the top, dated by when the change shipped, with a short description written for API users. Do not reference internal ticket numbers.
2026-11-10
Changed: code_quality.analysis_completed is not delivered to Marketplace apps
- An event only a workspace's staff may see is delivered only to webhook subscriptions the workspace created: one an admin created in Align, or one created with a workspace API key. Today that is
code_quality.analysis_completed; an internal note'sentry.commentedwas already delivered to no subscription. - It is not delivered to a subscription created with the key of an app installed from the Marketplace, or whose
destinationUrlsuch a key last changed, whether the subscription names the event or*. The app still receives every other event it subscribes to. Delivery is checked when the event is queued and again when it is sent. A subscription that an admin points somewhere else in Align is the workspace's again. - Subscriptions created before this change are treated as the workspace's own.
- The payload:
projectId,sonarProjectKey,branch(the branch analysed;mainwhen SonarQube named none),branchType(BRANCHorPULL_REQUEST),pullRequest(for a pull request),gateStatusandpreviousGateStatus(OK,WARN,ERRORorNONE;previousGateStatusisnullwhen Align knew no gate for that branch yet),taskId,analysedAt,revisionandsource.sourcesays how Align heard of the analysis:webhook(SonarQube's webhook reported it, andtaskIdis its task) orsweep(Align's own hourly or on-demand refresh found an analysis no webhook reported, andtaskIdisnull).analysedAtandrevisioncan benull. One analysis is announced at most once by each path, so a consumer that acts once per analysis keys it on the project, the branch or pull request, andanalysedAt.
Changed: get_code_quality answers a release with the release check's own decision
- With
releaseId, thereleaseblock is now the answer the release page shows and the release check applies when the release is marked shipped, so the three cannot disagree. It was the project's main branch, compared with the release's version. release.basisisrelease_check(it wasmain_branch). New fields:state(passed,failed,warn,missingorstale;nullwhen the project is not bound or SonarQube is not connected),message(the release check's sentence),branchReason,analysedAt,versionMatch(matched,differentorunknown),stale,staleReason,conditions,canBlock,mode(the project's release checks),blocksShippingandurl.branchis now the branch the gate was read from; it was alwaysnull.versionMatchesandanalysedVersionkeep their meaning, but versions are now compared as the release check compares them: a leadingvand letter case are ignored, so releaseV1.4.0matches an analysis of1.4.0.- An analysis nothing has refreshed for 24 hours is
stale(staleReason: "not_refreshed"), as on the release page, and never blocks. Before, only an analysis Align had marked stale was. - For a release,
summaryis the release check's sentence, and says when the gate blocks the release.
Changed: project responses no longer include two code-quality settings
GET /api/v1/projects/{id},GET /api/v1/projects, and the project returned byPOSTandPATCHincludedqualityGateCanBlockandsonarqubeSuggestMode, which are not in the API reference. They are no longer returned to any key. They were already not writable with a key.- MCP's
get_projectandlist_projectsinclude them only for staff of the project's workspace, by the role held there; aclient,userorviewerdoes not get them.
Added: the MCP tool get_code_quality
get_code_qualityreads a project's SonarQube code quality as Align last stored it: the quality gate'sstatus(greenwhen it passes) with itsfailingConditions, the key measures, when the main branch was last analysed, and the gates of other branches and pull requests. PassreleaseIdfor a release (answered from the main branch, with the release'sversionandversionMatches), orentryIdfor the SonarQube issues linked to an entry and their last-known status. It is read-only and never sends anything to SonarQube.- Only the workspace's staff can use it, by the role they hold in that workspace. A
client,userorviewergetsstaff_only, whatever they ask for. A project that is not bound answersstatus: "not_bound", and a workspace without SonarQube answersstatus: "not_connected". - Project-scoped keys can call it for their own project.
- While Forward Rise has paused the SonarQube app for every workspace, the answer is the last stored one, with
stale: trueandstaleReason: "paused".
Added: the SonarQube quality gate in release checks
ReleaseOpenItem.kindhas a new value,quality_gate. It can appear inblockingorwarningswherever release checks are reported: the 409release_checks_openbody ofPATCH /api/v1/releases/{id}andPOST /api/v1/projects/{id}/releases, andreleaseCheckson a release they write. MCP'supdate_releasereports it the same way.- It appears only for a project bound to a SonarQube project, in a workspace where SonarQube is connected. A passing gate adds nothing.
- A failing quality gate is a warning. It is blocking only when the project has turned on SonarQube quality gate can block in Align and its release checks are
block;overrideReasonthen overrides it as it does any other blocking item. That setting is not writable with an API key. - An analysis that is out of date, or missing, is always a warning. So is any gate while Forward Rise has paused the SonarQube app: Align can't vouch for a gate it is not reading, so it never blocks then;
messagesays the app is paused. messagenames the SonarQube project, the failing conditions and the analysis that was read; for a failing gate,countis the number of failing conditions. That detail is shown only when the key's creator is staff of the project's workspace, by the role they hold there. For any other key aquality_gatewarning is left out, and a blocking one reads "A check that only this workspace's staff can see is failing. Ask them about it." withcount1. The release is still blocked.
2026-11-09
Changed: marking a release shipped meets the project's release checks
- Each project now has a release checks setting:
block,warnoroff. A project with no setting uses its default:blockfor a project owned by a client of its workspace,warnfor an internal project. Admins and managers change it on the project's settings page; it is not writable with an API key. PATCH /api/v1/releases/{id}that moves a release intoreleasedorcompletedfrom any other status, andPOST /api/v1/projects/{id}/releasesthat creates one alreadyreleasedorcompleted, now meet those checks. Saving a release that is already shipped is not judged again.- In
blockmode the request answers 409 (reason: "release_checks_open") while anything blocking is open on the release: its approval workflow (pending or rejected — a release with no approval of its own is under the project's default release workflow), legacy approval gates, entries still awaiting the client's approval, or a cost sign-off that was submitted and not finished (an entry's or the release's committed cost). Nothing is written. The body listsblockingandwarnings; each item haskind,count,messageand up to tenrefs. - Unfinished dependencies, a release it depends on that has not shipped, open checklist items and open bugs are only ever
warnings. - In
warnmode, and inblockmode with nothing blocking, the write goes through and the release returned carriesreleaseChecks(mode,overridden,blocking,warnings). Inoffmode nothing changes. - Added:
overrideReasonon both release bodies. It overrides a block when the key's creator is an admin of the key's workspace (by the role they hold there) or a platform operator, and the override is recorded in the workspace's audit log with the reason and what was open. A blank reason answers 400 (reason: "override_reason_required"); any other creator gets 403 (reason: "override_not_allowed"). It is not stored on the release. - MCP:
update_releasemeets the same checks and takesoverrideReason(honoured for an admin of the workspace). Changing a release's status throughupdate_releasenow needs an admin or manager of the workspace, as in the app; developers, testers and the other write roles can still change a release's name, description and dates.
Changed: a key stops working when the person who created it can no longer act in its workspace
- A key acts as the person who created it: what it writes is theirs. Every request made with a key — Public API, SCIM and MCP — now answers 401 (
reason: "key_revoked") once that person's account is suspended or archived, or they are no longer an active member of the key's workspace (removed from it, or deprovisioned there by your identity provider). A platform operator's key follows the operator's account the same way. - When that happens from now on, the key is also revoked, so it stays revoked if the person is reactivated or added back. Mint a new key.
- The same applies to a key created, or an MCP authorization granted, by the founder of a workspace that signed up on its own and never verified its email address: that account can no longer sign in, so the key answers 401 (
reason: "key_revoked") and the authorization stops working, with no new token issued on refresh. - Keys whose creator had already left, or been suspended, before this change are refused from now on but are not revoked yet. Until Align revokes them, such a key works again if its creator regains access. Mint a new key rather than rely on that.
- This includes organization-scoped keys, Marketplace installation keys and SCIM tokens. If the person who installed an app or created your SCIM token leaves the workspace, a current admin re-issues the installation's key from the installed app, or mints a new SCIM token.
Changed: webhooks are delivered only to public https destinations
POSTandPATCH /api/v1/webhooksnow refuse (400 validation_error) adestinationUrlthat is not anhttps://URL on a public host: a loopback, private, link-local or otherwise non-public address, written in any form,localhost,*.internal, or a name that resolves to such an address. Before, only thehttps://prefix was checked.- Every delivery is checked again when it is sent. A subscription that no longer passes is not sent anything; each delivery is dead-lettered with "Destination not allowed" and not retried. Edit the
destinationUrlto resume. - Redirects are no longer followed. A 3xx response is a failed delivery, recorded and not retried.
- Your endpoint's response body is no longer stored, and was never part of the API.
POST /api/v1/webhooks/{id}/testnow needswrite:webhookinstead ofread:webhook. ItsdeliveryErroris now also present for a 3xx or 4xx response.
2026-11-08
Changed: internal notes are never delivered to webhooks
entry.commentedis no longer delivered for an internal note, to any webhook subscription: one created by a workspace admin, by an API key (POST /api/v1/webhooks) or by a marketplace app. Until now a subscription received internal notes too, withisInternal: trueand the note's first 200 characters inbodyPreview.- A delivery already queued for a comment that is made internal before it is sent is not sent either.
- A delivered
entry.commentedtherefore always hasisInternal: false. The field stays in the payload. - Comments the client can see are delivered exactly as before.
Changed: the audit trail leaves out internal notes for a key whose creator cannot read them
GET /api/v1/audit-eventsno longer returns the events about an internal note (they hold the note, text included) unless the key's creator can read internal notes in the key's workspace: a platform operator, or an active member whose role there is a staff role. This is the ruleGET /api/v1/entries/{id}/commentsalready uses.- For any other key those events are left out, and
totalcounts only the events returned.
Changed: wiki pages keep only a short list of HTML tags
- Wiki content written with
POST /api/v1/projects/{id}/wiki-pagesorPATCH /api/v1/wiki-pages/{id}is now saved with its raw HTML limited. Outside code spans and fenced code blocks,<br>,<sub>,<sup>,<kbd>,<mark>,<details>and<summary>are kept, without attributes (<details>may keepopen). Any other tag, an HTML comment or anything<!…>is saved escaped, so<div>is stored as<div>and shows as the text that was sent. - A
<that does not start a tag, as ina < b, is saved as sent. Code spans and fenced blocks are saved as sent. - The
contenta page returns is what was saved. Pages saved before this change are not rewritten; Align shows their other HTML as text.
Changed: a key deletes someone else's comment only when its creator is an admin of the workspace
DELETE /api/v1/comments/{id}now answers 403 (reason: "forbidden") for a comment someone else wrote, unless the key's creator is an admin of the key's workspace (by the role they hold there) or a platform operator. Until now any key withdelete:commentcould delete any comment in its workspace, including a key created by a client.- A key still deletes its creator's own comments, as before.
- A refused request deletes nothing.
- An internal note the key's creator cannot read still answers 404, as a missing comment does.
- This is the rule Align itself applies when someone deletes a comment in the app.
Changed: only a key whose creator can read internal notes can write one
POST /api/v1/entries/{id}/commentswithisInternalset, andPATCH /api/v1/comments/{id}settingisInternal, now answer 403 (reason: "forbidden") unless the key's creator can read internal notes in the key's workspace: a platform operator, or an active member whose role there is a staff role (admin, manager, developer, tester, tech lead, product owner or DevOps engineer). Until now any key withwrite:commentcould post an internal note, including a key created by a client, a portal user or a viewer, whose ownGETthen hid it.- A refused request posts nothing: the comment is not posted as a visible comment instead, and a refused
PATCHleaves the comment as it was. - Comments without
isInternal(or with itnull) are unchanged, as is everything else these operations do. - The rule is the one
GET /api/v1/entries/{id}/commentsuses to decide who sees internal notes, so a key can now write an internal note exactly when it can read one back.
2026-11-07
Removed: fields that record who did something, from the comment, attachment and release write bodies
POST /api/v1/entries/{id}/commentsandPATCH /api/v1/comments/{id}no longer takeisAiGenerated. A comment posted with an API key is its creator's and is not AI-generated, as a comment posted in Align is;PATCHno longer changes whether a comment reads as AI-written.POST /api/v1/entries/{id}/attachmentsno longer takesisAiGenerated,linkedByUserIdorremovedByUserId. The uploader is the key's creator, as before.PATCH /api/v1/releases/{id}no longer takescostUpdatedById; the one Align recorded stays.POST /api/v1/projects/{id}/releasesalready ignored it.- A request that still sends one of these fields is not refused, on
PATCHas onPOST: the field is ignored and the rest of the request is applied.PATCH /api/v1/comments/{id}withauthorId, which answered 400, now ignores it too, and aPATCHleft with nothing to change returns the comment as it is. - These fields are still returned on comments, attachments and releases.
- SDKs (still 1.0.0):
entries.createCommentandcomments.updateno longer takeisAiGenerated. TypeScript drops it from the body types; Python refuses it before sending, as it does any field an operation does not take.
2026-10-28
Removed: approvalStatus and costApprovalStatus from the entry write bodies
POST /api/v1/projects/{id}/entriesno longer takesapprovalStatusorcostApprovalStatus; a value sent is ignored, and a new entry starts asapprovedwith its cost atdraft, as before when the fields were left out.PATCH /api/v1/entries/{id}now answers 400 when either field is in the body. An approval is recorded by the approval flow (in Align, or through the MCP cost approval tools), which also records who decided; the API could set the status with nobody on record.- Both fields are still returned on every entry.
Changed: project updates follow the same rules as in Align
PATCH /api/v1/projects/{id}now refuses, as the app does, aprogramIdthat is not a program of the project's workspace (400), akindother thansoftwareorbusiness(400), and a change tocommittedCostonce billing has locked it (409,reason: "committed_cost_locked"; use the change-order flow in Align).
Fixed: refreshing an authorisation that was granted no scopes
- An MCP authorisation granted before 2026-10-24 with no scopes stayed unusable after every refresh. A refresh now grants
align:read, which is what the consent screen showed, so the connection works without re-authorising.
Added: delivery of the time, agreement, code, user and project member events
- Subscriptions now receive
time.logged,time.updated,time.deleted,time.submitted,time.approved,time.rejected,time.unlocked,agreement.signed,pr.mergedandcommit.linked. These were accepted and recorded but never delivered, because Align could not work out which workspace they belonged to. - The public API now emits, and Align delivers,
user.invited,user.linked,user.updatedanduser.bulk_invitedfromPOST /api/v1/users/invite,POST /api/v1/users/bulk-inviteandPATCH /api/v1/users/{id}, andproject_member.added,project_member.updatedandproject_member.removedfrom the/api/v1/projects/{id}/membersroutes. user.invitedfor an emailed invitation carriesuserId: null,invitationIdandpending: true; a user provisioned directly carries itsuserIdandpending: false.x-align-events-not-yet-deliverednow lists six names:integration_link.created,integration_link.updated,subscription.updated,pi_board.updated,pi_board.publishedandpi_board.deleted.- See Webhooks for the payload fields of each family.
2026-10-23
Changed: three new entry statuses
- Entry
statuscan now also beblocked,testinganddone. In workflow order the statuses areopen,assigned,in_progress,blocked,testing,deployed,done,solved.donefollowsdeployed;solvedmeans closed without a deploy. - The new values appear in entry responses, are accepted by
POST /api/v1/projects/{id}/entriesandPATCH /api/v1/entries/{id}, and appear inentry.status_changedwebhook payloads. If your integration checks status against a fixed list, add the new values. - Align now moves entries to
testingwhen they are deployed to a testing or staging environment, and closes verified entries asdone.
Fixed: the OpenAPI spec and both SDKs match the API
- Every operation in
openapi.jsonnow has anoperationId, names the permission it checks (x-required-permission), and marks the Illumera add-on (x-requires-addon) and time-tracking (x-requires-feature) gates. Every operation documents423 suspended; time-tracking operations document402 feature_disabled. - The spec now describes what the server returns: comments have
content(notbody), time entries have their real columns (notes,invoicedAt, the approval fields; there is noinvoicedflag), approve setslocked, time and cost summaries return minute totals, invites returncreated/linked/updatedwithpending, bulk invites return asummary, and member, wiki, snapshot, search, audit and agreement shapes and enums are corrected. - Added to the spec and both SDKs:
GET /api/v1/time-entries,GET /api/v1/projects/{id}/releases/{releaseId}/time-summary,GET /api/v1/users/{id}/time-summaryandPOST /api/v1/ci/test-runs(permissionwrite:test_run). - Removed from the SDKs:
comments.retrieveandattachments.retrieve, which called routes that do not exist. - SDK changes (still 1.0.0, not yet published): the default base URL is
https://app.alignsoft.us/api/v1; bodies and parameters are typed from the spec (createEntryneedstype,titleanddescription;timeEntries.rejectneedsreason;projects.addMembertakes the user id in the body); a POST is retried only on 429 or with an idempotency key;AlignApiErrorparses non-JSON and legacy{ error }bodies and readsretryAfterfromdetailsor theRetry-Afterheader;releases.getEvidencereturns the signature headers. - CI now fails when either SDK drifts from the spec: method, path, parameters, body fields and enums are compared in both directions.
Fixed: request handling
POST /api/v1/users/bulk-invitehonours a top-levelsendInvite: false. An item's ownsendInvitestill wins.PATCH /api/v1/projects/{id}/members/{userId}withroleOverride: nullnow removes the override.- Time-entry lists and summaries accept
startDate/endDateand, as deprecated aliases,workDateFrom/workDateTo(what the SDKs used to send, and which were ignored). GET /api/v1/integration-linksnow filters byalignEntityId.- The
addon_required,unknown_event_names, unlockinsufficient_roleand webhook-testrate_limiterrors now use the{ reason, message, details }envelope. The old top-level fields are still sent. - Keys can now be given
write:wiki,delete:wikianddelete:time_entry, which those routes already checked but the key editor did not offer. The organisation default includes them.
Changed: webhook vocabulary
- Added
project.transfer_initiatedandproject.transferred. - Thirteen events that nothing emits yet are marked "not yet delivered" in the docs and listed in the spec's
x-align-events-not-yet-delivered.
2026-10-22
Fixed: agreements scoped to your organisation
GET /api/v1/projects/{id}/agreementscould include an agreement from another organisation that pointed at the same project ID. It now returns only your organisation's agreements.
2026-10-20
Changed: MCP consent lets you choose the workspace
- The OAuth consent screen now lists the organisations you belong to where MCP is turned on, and you choose which one to authorise. It defaults to the workspace you are working in. Before, it always authorised your original organisation. See MCP Integration.
Changed: suspended and archived users lose OAuth access
- A suspended or archived user can no longer complete OAuth authorization or refresh a token (
400 invalid_grant, "User account is not active"), and their existing access tokens stop working.
Changed: invitation links
- Invitation emails sent by
POST /api/v1/users/inviteandPOST /api/v1/users/bulk-invitelink to Align's configured address (https://app.alignsoft.us), not to the host the request was sent to.
Clarified: request size
- Align's inbound webhook receivers (for example the GitHub and Stripe webhooks) now accept payloads up to 25 MB. Every other endpoint, including
/api/v1, still accepts JSON bodies up to 100 KB.
2026-09-18
Changed: MCP uses your role in the active organisation
- MCP tools now decide what you may do from your role in the organisation you are working in, not from your account's original role. Someone who is a
clientin one organisation is treated as a client there, even if they are adeveloperelsewhere.
2026-09-14
Removed: Slack webhook URL from project responses
- Project responses from
GET /api/v1/projectsandGET /api/v1/projects/{id}no longer include the project's Slack webhook URL (slackWebhookUrl, or its encrypted formslackWebhookUrlEnc). It is a credential.
Changed: time entry pricing
- Time entries created with
POST /api/v1/projects/{id}/time-entriesandPOST /api/v1/integration/time-entriesare now priced from the person's labour category for that project, the same way as time logged in Align.
2026-09-08
Added: service levels on projects
POST /api/v1/projectsandPATCH /api/v1/projects/{id}acceptslaEnabledandslaTargets.
Changed: clearer MCP refusals
- When a record exists but is outside your current MCP context (another organisation, or a project your key is not pinned to), MCP tools now say so instead of reporting "not found".
2026-09-07
Added: per-project workflow states
POST /api/v1/projects/{id}/entriesandPATCH /api/v1/entries/{id}acceptworkflowStatusId, for projects that define their own workflow states.
Added: setting custom fields through MCP
- The MCP
entry_createandentry_updatetools acceptcustomFields.
2026-09-06
Added: custom fields in MCP
get_entryand thealign://entries/{id}resource include an entry's custom fields.list_entriesincludes the fields the project marks for lists.
2026-09-04
Fixed: MCP context on the SSE transport
- Each SSE connection now keeps its own active organisation and project, as Streamable HTTP connections already did.
2026-09-03
Added: cost rate on time entries
- Time entries created through the API now record
costRateSnapshot, the cost rate at the time of logging, alongsidehourlyRateSnapshot.
2026-09-02
Added: SCIM 2.0 provisioning
- Identity providers can provision and deprovision users through SCIM 2.0 at
https://app.alignsoft.us/scim/v2(/Usersand/ServiceProviderConfig). Authenticate with an API key that holdsread:scim_user,write:scim_useranddelete:scim_user. SCIM uses the same key checks as the Public API, so the Public API must be turned on for the organisation.
Changed: GET /users lists members by membership
GET /api/v1/usersnow lists everyone who is a member of your organisation. Before, it relied on an older per-user field, so it could miss members or list someone under an organisation they had left.
Changed: archived organisations
- Keys belonging to an archived or deleted organisation are refused with
403 organization_unavailable.
Fixed: MCP semantic search
semantic_searchsearched projects the caller could not open. It now searches only projects you can access.
2026-09-01
Changed: MCP follows project access
- MCP tools and resources now show only the projects you can access in Align, instead of every project in the organisation. For an API key, that is the access of the user who created it.
- MCP cost tools check your role in the active organisation.
Added: separate context per MCP connection
- Each Streamable HTTP connection gets its own active organisation and project, identified by the
Mcp-Session-Idheader. Switching project in one client no longer moves another.
Corrections to earlier entries
Earlier versions of this changelog described some things that are not in the API. They have been removed from the entries below:
POST /api/v1/webhooks/{id}/rotate-secret(2026-04-10) does not exist. To change a subscription's secret, create a new subscription and delete the old one.GET /api/v1/agreements/{id}(2026-05-03) does not exist. UseGET /api/v1/projects/{id}/agreements.GET /api/v1/projects/{id}/audit-events(2026-04-28) does not exist. UseGET /api/v1/audit-events.- Project-scoped keys cannot call
GET /api/v1/users(2026-04-21); it needs an organisation-scoped key. GET /api/v1/search(2026-04-15) returns up to 50 results; the earlier entry said 25.GET /mcp/privacy(2026-06-04) is not served.GET /api/v1/comments/{id}(2026-03-20) does not exist; comments are read withGET /api/v1/entries/{id}/comments.
2026-06-04
Added: entry deployment stage tracking
- Entry response objects now include a
deploymentStagefield ("testing"|"staging"|"production"|null). The field is set automatically by the Railway deployment webhook or the GitHubdeployment_statuswebhook when a matching entry is deployed to a tracked environment. It is read-only via the API —deploymentStageis ignored inPOST /api/v1/projects/:id/entriesandPATCH /api/v1/entries/:idbodies.
Added: MCP server compliance
GET /.well-known/oauth-protected-resource— returns RFC 9728 OAuth Protected Resource metadata. Used by MCP clients (Claude.ai, CODEX) to discover the token endpoint before connecting.- All 22 MCP tools now carry OpenAPI-compatible tool annotations (
title,readOnlyHint,openWorldHint,destructiveHint). Clients that support tool annotations can use these to surface safe-for-automation indicators in their UI. - MCP endpoints now enforce an origin allowlist and return
403 Forbiddenfor requests from unlisted origins.
2026-05-14
Added: release evidence signing key management
GET /api/settings/evidence-key— returns whether a signing key is configured and its key prefix (evk_<prefix>). Requires admin role.POST /api/settings/evidence-key— generate (or rotate) the organisation-level HMAC signing key for release evidence packages. Issuing a new key automatically revokes the previous one. The full key (evk_<64hex>) is returned once; store it in your secrets manager immediately.- Evidence responses now include
X-Align-Evidence-Signature: sha256=<hex>andX-Align-Evidence-Key-Prefix: evk_<prefix>headers when a signing key is configured.
Note: These endpoints are session-authenticated platform-settings routes (
/api/settings/) — they are not part of the public v1 API and do not appear in the OpenAPI spec. They are accessible to org admins via the Align web app only.
2026-05-10
Added: snapshot (report) endpoints
GET /api/v1/projects/:id/snapshots— list report snapshots for a project. Each snapshot includesnarrativeSource('ai'or'template') and the generated summary text.
The narrativeSource field indicates whether the executive summary was produced by the AI provider or fell back to the template generator (e.g. when the AI provider is unavailable or the prompt was redacted).
Note: Individual snapshot retrieval (
GET /api/v1/snapshots/:id) is not yet available in the public API. Use the project list endpoint and filter client-side byid.
2026-05-07
Added: wiki page endpoints
GET /api/v1/projects/:id/wiki-pages— list wiki pages for a project.POST /api/v1/projects/:id/wiki-pages— create a wiki page. Required fields:title. Optional:content(Markdown).GET /api/v1/wiki-pages/:id— retrieve a single wiki page with full Markdown content.PATCH /api/v1/wiki-pages/:id— update title or content.DELETE /api/v1/wiki-pages/:id— delete a wiki page.
2026-05-03
Added: agreement endpoints
GET /api/v1/projects/:id/agreements— list agreements for a project.
Creating agreements via the API is not supported in v1.
2026-04-28
Added: audit event endpoint
GET /api/v1/audit-events— list audit events across the organisation, paginated. SupportsentityType,action, andactorIdquery filters.
Audit events include actorType: 'api_key' and apiKeyId in metadata when the action was performed via an API key.
2026-04-21
Added: user endpoints
GET /api/v1/users— list users in the organisation, paginated. Returnsid,name,email,role,organizationId, andcreatedAt. Sensitive fields (password hash, MFA secrets) are excluded.GET /api/v1/users/:id— retrieve a single user.
2026-04-15
Added: global search endpoint
GET /api/v1/search?q=<query>— search across the organisation.
2026-04-10
Added: outbound webhook subscriptions
GET /api/v1/webhooks— list webhook subscriptions.POST /api/v1/webhooks— create a subscription.hmacSecretis returned once on creation.PATCH /api/v1/webhooks/:id— updatedestinationUrl,eventNames,enabled, ordescription.DELETE /api/v1/webhooks/:id— delete a subscription.
2026-04-01
Added: release evidence endpoint
GET /api/v1/releases/:id/evidence— retrieve a structured evidence package for a release, including the approval chain, quality checklists, entry summary, and GitHub evidence (commits, PRs, CI results).
2026-03-20
Added: core resource endpoints (initial v1 launch)
Initial set of endpoints released:
GET /api/v1/me— API key identityGET|POST /api/v1/projects— list and create projectsGET|PATCH|DELETE /api/v1/projects/:idGET|POST /api/v1/projects/:id/entries— list and create entriesGET|PATCH|DELETE /api/v1/entries/:idGET|POST /api/v1/entries/:id/commentsPATCH|DELETE /api/v1/comments/:idGET /api/v1/entries/:id/attachmentsGET|POST /api/v1/projects/:id/releasesGET|PATCH|DELETE /api/v1/releases/:id