Trigger API Reference
This page is not normative
This page is not considered a core part of the Vultron Protocol as proposed in the main documentation. Although within the page we might provide guidance in terms of SHOULD, MUST, etc., the content here is not normative.
The Vultron reference implementation exposes its general-purpose protocol trigger endpoints at POST /actors/{actor_id}/trigger/{behavior}; the table below is generated from the running application, so it lists every endpoint the build knows.
Each endpoint initiates a protocol behavior on behalf of the specified actor; the decision to act has already been made by the caller.
Every endpoint has one row in the trigger registry (vultron/trigger_registry/), which records its request model, use case, result type and whether it is general-purpose or demo-only.
All endpoints accept JSON request bodies, return HTTP 202 on success with the resulting ActivityStreams activity in the response body, and run behavior execution as a background task so the HTTP response is not blocked.
Interactive exploration
When running the reference implementation locally, visit /docs for an
interactive Swagger UI over the same schema this page is generated from.
For a conceptual overview of how trigger endpoints fit into the two-surface integration model, see Wiring a Capability.
Report Management
For the workflow view, see How to Report a Vulnerability.
submit-report
POST /api/v2/actors/{actor_id}/trigger/submit-report
Creates a VulnerabilityReport in the actor's DataLayer and queues an RmSubmitReportActivity (Offer) to the specified recipient. An optional proposed_embargo_end_time states the Reporter's embargo terms for the report; the Offer then carries them as proposedEmbargo (EP-04-004). Returns the serialised offer so the caller can deliver it to the recipient's inbox.
Request body (SubmitReportRequest):
| Field | Type | Required |
|---|---|---|
report_name |
string |
Yes |
report_content |
string |
Yes |
recipient_id |
string |
Yes |
proposed_embargo_end_time |
string |
No |
ack-report
POST /api/v2/actors/{actor_id}/trigger/ack-report
Triggers the ack-report behavior for the given actor. Emits a Read(Offer(VulnerabilityReport)) activity (RK) to the reporter and returns it in the response body (TRIG-04-001). Only an actor the Offer was addressed to may acknowledge it; it may do so whether or not a case exists, and RK is never sent to the CASE_MANAGER (RMB-08-003).
Request body (AckReportRequest):
| Field | Type | Required |
|---|---|---|
offer_id |
string |
Yes |
note |
string |
No |
validate-report
POST /api/v2/actors/{actor_id}/trigger/validate-report
Triggers the validate-report behavior for the given actor. Invokes the ValidateReportBT tree via the bridge layer and returns the resulting ActivityStreams activity (TRIG-04-001).
Request body (ValidateReportRequest):
| Field | Type | Required |
|---|---|---|
offer_id |
string |
Yes |
note |
string |
No |
invalidate-report
POST /api/v2/actors/{actor_id}/trigger/invalidate-report
Triggers the invalidate-report behavior for the given actor. Emits a TentativeReject(Offer(VulnerabilityReport)) activity (RmInvalidateReportActivity) and returns it in the response body (TRIG-04-001). Persists a ParticipantStatus record with RM.INVALID for the actor and report.
Request body (InvalidateReportRequest):
| Field | Type | Required |
|---|---|---|
offer_id |
string |
Yes |
note |
string |
No |
reject-report
POST /api/v2/actors/{actor_id}/trigger/reject-report
Triggers the reject-report behavior for the given actor. Emits a Reject(Offer(VulnerabilityReport)) activity (RmCloseReportActivity) and returns it in the response body (TRIG-04-001). A non-empty note is required (TRIG-03-004). Persists a ParticipantStatus record with RM.CLOSED for the actor and report. Returns HTTP 409 if the report's RM state has no close edge (e.g. VALID; VP-02-004), or if a case holds the report, whose participants close their part in it with leave-case instead (CM-23-019, TRIG-13-001): nothing is emitted.
Request body (RejectReportRequest):
| Field | Type | Required |
|---|---|---|
offer_id |
string |
Yes |
note |
string |
Yes |
Case Management
For the workflow view, see How to Manage a Case.
create-case
POST /api/v2/actors/{actor_id}/trigger/create-case
Creates a local VulnerabilityCase attributed to the actor and queues a CreateCaseActivity in the actor's outbox for delivery to the CaseActor. An optional report_id links an existing VulnerabilityReport to the new case.
Request body (CreateCaseRequest):
| Field | Type | Required |
|---|---|---|
name |
string |
Yes |
content |
string |
Yes |
report_id |
string |
No |
to |
list[string] |
No |
engage-case
POST /api/v2/actors/{actor_id}/trigger/engage-case
Triggers the engage-case behavior for the given actor. Emits a Join(VulnerabilityCase) activity (RmEngageCaseActivity), addressed to the CASE_MANAGER, which records the actor's RM ACCEPTED; the actor's replica copies that status from the ledger, and returns the activity in the response body (TRIG-04-001).
Request body (CaseTriggerRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
defer-case
POST /api/v2/actors/{actor_id}/trigger/defer-case
Triggers the defer-case behavior for the given actor. Emits an Ignore(VulnerabilityCase) activity (RmDeferCaseActivity), addressed to the CASE_MANAGER, which records the actor's RM DEFERRED; the actor's replica copies that status from the ledger, and returns the activity in the response body (TRIG-04-001).
Request body (CaseTriggerRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
add-report-to-case
POST /api/v2/actors/{actor_id}/trigger/add-report-to-case
Links a VulnerabilityReport to an existing VulnerabilityCase and queues an AddReportToCaseActivity in the actor's outbox addressed to the case's CASE_MANAGER alone (PCR-08-005). Returns 422 and queues nothing when the case has no CASE_MANAGER.
Request body (AddReportToCaseRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
report_id |
string |
Yes |
add-object-to-case
POST /api/v2/actors/{actor_id}/trigger/add-object-to-case
Adds any existing AS2 object (identified by object_id) to a VulnerabilityCase and queues an Add(object, target=case) activity in the actor's outbox addressed to the case's CASE_MANAGER alone, which commits it and replicates it to the participants (PCR-08-005). The object must already exist in the actor's datalayer. Returns 422 and queues nothing when no receiver would route the object as an addition to the case, when its type has its own flow (EmbargoEvent, CaseParticipant, CaseStatus), or when the case has no CASE_MANAGER. Type-specific convenience triggers (e.g., add-report-to-case) delegate here after performing type validation (TRIG-10-001).
Request body (AddObjectToCaseRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
object_id |
string |
Yes |
leave-case
POST /api/v2/actors/{actor_id}/trigger/leave-case
Triggers the leave-case behavior for the given actor, which any participant of the case may call (TRIG-13-001). Runs the actor's PreCloseAction call-out, then queues a Leave(VulnerabilityCase) activity addressed to the case's CASE_MANAGER alone, and returns it in the response body (TRIG-04-001). The CASE_MANAGER decides what the Leave means: the Case Owner's Leave closes the case, and any other participant departs while the case stays open (CM-23-002, CM-23-003). Returns HTTP 409 and queues nothing when the caller is the Case Owner and its replica records an active embargo: terminate the embargo first (TRIG-13-003). Returns HTTP 422 and queues nothing when the PreCloseAction call-out fails (TRIG-13-002).
Request body (LeaveCaseRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
Embargo Management
For the workflow view, see How to Establish an Embargo.
propose-embargo
POST /api/v2/actors/{actor_id}/trigger/propose-embargo
Triggers the propose-embargo behavior for the given actor. Creates a new EmbargoEvent and emits an EmProposeEmbargoActivity (Invite(EmbargoEvent)) activity. EM state transitions: N → P (new proposal) or A → R (revision). Returns the resulting activity in the response body (TRIG-04-001).
Request body (ProposeEmbargoRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
note |
string |
No |
end_time |
string |
Yes |
accept-embargo
POST /api/v2/actors/{actor_id}/trigger/accept-embargo
Triggers the accept-embargo behavior for the given actor. A participant accepts the current (or specified) embargo proposal with Accept(Invite(EmbargoEvent)), which records its own consent and moves no EM state. The case owner's accept is its decision for the case, Accept(EmbargoEvent, target=Case), which activates the embargo (EM state → ACTIVE). Returns the resulting activity in the response body (TRIG-04-001).
Request body (AcceptEmbargoRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
proposal_id |
string |
No |
reject-embargo
POST /api/v2/actors/{actor_id}/trigger/reject-embargo
Triggers the reject-embargo behavior for the given actor. A participant rejects the current (or specified) embargo proposal with Reject(Invite(EmbargoEvent)), which records its own refusal and moves no EM state. A CASE_MANAGER that is not the owner records its own refusal as its Update(EmbargoConsent) of its row instead, and sends no Reject: the CASE_MANAGER's Reject of a proposal is its abandonment of it (MSM-07-004). The case owner's reject is its decision for the case, Reject(EmbargoEvent, target=Case), which rejects the proposal (EM state PROPOSED → NONE or REVISE → ACTIVE, or unchanged while another proposal is open). When the owner is also the CASE_MANAGER and rejects the last open revision while CS is public, exploited, or attacked, the rejection also terminates the embargo in the same act (EM → EXITED), committed as the Reject entry followed by the owner's ET Remove(EmbargoEvent) entry; a refused termination commits neither (MSM-07-009, EMB-04-002). Returns the resulting activity in the response body (TRIG-04-001).
Request body (RejectEmbargoRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
proposal_id |
string |
No |
propose-embargo-revision
POST /api/v2/actors/{actor_id}/trigger/propose-embargo-revision
Triggers the propose-embargo-revision behavior for the given actor. Proposes a revision to the active embargo by emitting an EmProposeEmbargoActivity activity. Only valid when EM state is ACTIVE or REVISE; use propose-embargo for initial proposals. EM state transitions: ACTIVE → REVISE or REVISE → REVISE. Returns the resulting activity in the response body (TRIG-04-001).
Request body (ProposeEmbargoRevisionRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
note |
string |
No |
end_time |
string |
Yes |
terminate-embargo
POST /api/v2/actors/{actor_id}/trigger/terminate-embargo
Triggers the terminate-embargo behavior for the given actor. Ends the active embargo with a Remove(EmbargoEvent) activity. Updates the case EM state to EXITED and clears the active embargo. An EARLY request may name its cause (FIX_READY with its vendors, FIX_DEPLOYED or OTHER); one that names none is recorded as OTHER. A THREAT_SIGNAL cause, or any cause on END_TIME_REACHED, is refused with HTTP 422 (EMB-13-004, EMB-13-005). Returns HTTP 409 if no active embargo exists. Returns the resulting activity in the response body (TRIG-04-001).
Request body (TerminateEmbargoRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
reason |
TerminationReason |
No |
cause |
any |
No |
Actor Participation
For the workflow view, see How to Manage Case Participants.
suggest-actor-to-case
POST /api/v2/actors/{actor_id}/trigger/suggest-actor-to-case
Emits a RecommendActorActivity addressed to the case owner (typically the CaseActor). The CaseActor then autonomously invites the suggested actor via RmInviteToCaseActivity.
Request body (SuggestActorToCaseRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
suggested_actor_id |
string |
Yes |
roles |
list[CVDRole] |
No |
invite-actor-to-case
POST /api/v2/actors/{actor_id}/trigger/invite-actor-to-case
Sends the case owner's Offer of the invitee, with the offered roles, to the case's CASE_MANAGER, which emits and commits the Invite (ADR-0109). The case must exist in the actor's DataLayer.
Request body (InviteActorToCaseRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
invitee_id |
string |
Yes |
roles |
list[CVDRole] |
No |
accept-actor-recommendation
POST /api/v2/actors/{actor_id}/trigger/accept-actor-recommendation
Emits an Accept(Offer(CaseParticipant)) from the Case Owner's identity addressed to the CaseActor, completing the ADR-0026 CM-16-006 approval step. The Offer(CaseParticipant) must already exist in the actor's DataLayer (delivered by the CaseActor).
Request body (AcceptActorRecommendationRequest):
| Field | Type | Required |
|---|---|---|
cp_offer_id |
string |
Yes |
case_actor_id |
string |
Yes |
accept-case-invite
POST /api/v2/actors/{actor_id}/trigger/accept-case-invite
Accepts an RmInviteToCaseActivity by emitting an RmAcceptInviteToCaseActivity queued in the actor's outbox for delivery to the case owner.
Request body (AcceptCaseInviteRequest):
| Field | Type | Required |
|---|---|---|
invite_id |
string |
Yes |
reject-case-invite
POST /api/v2/actors/{actor_id}/trigger/reject-case-invite
Rejects an RmInviteToCaseActivity by emitting an RmRejectInviteToCaseActivity queued in the actor's outbox for delivery to the case owner.
Request body (RejectCaseInviteRequest):
| Field | Type | Required |
|---|---|---|
invite_id |
string |
Yes |
offer-case-participant-role
POST /api/v2/actors/{actor_id}/trigger/offer-case-participant-role
Emits Offer(CaseParticipantRole, target=Actor, context=VulnerabilityCase) from the requesting actor. This is the canonical role-delegation wire format introduced by ADR-0039, replacing the deprecated offer-case-manager-role endpoint. The Offer is addressed to the case's CASE_MANAGER, which forwards it to the target. The role field is required, and the CASE_MANAGER refuses an Offer of CASE_OWNER or CASE_MANAGER (CM-33-003). See SE-08-003.
Request body (OfferCaseParticipantRoleRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
target_actor_id |
string |
Yes |
role |
CVDRole |
Yes |
offer-case-ownership-transfer
POST /api/v2/actors/{actor_id}/trigger/offer-case-ownership-transfer
Emits the requesting Case Owner's proposal, an Offer(Offer(VulnerabilityCase)), to the case's CASE_MANAGER, which offers the case to the specified transferee on the owner's behalf. The case must exist in the actor's DataLayer. The transferee must also be known. The returned activity is the proposal, which the withdraw trigger names (TRIG-11-001).
Request body (OfferCaseOwnershipTransferRequest):
| Field | Type | Required |
|---|---|---|
case_id |
string |
Yes |
transferee_id |
string |
Yes |
content |
string |
No |
end_time |
string |
No |
accept-case-ownership-transfer
POST /api/v2/actors/{actor_id}/trigger/accept-case-ownership-transfer
Emits an Accept(Offer(VulnerabilityCase)) from the accepting actor to the case's CASE_MANAGER. The ownership transfer offer must already exist in the actor's DataLayer (TRIG-11-002, CM-21-006).
Request body (AcceptCaseOwnershipTransferRequest):
| Field | Type | Required |
|---|---|---|
offer_id |
string |
Yes |
reject-case-ownership-transfer
POST /api/v2/actors/{actor_id}/trigger/reject-case-ownership-transfer
Emits a Reject(Offer(VulnerabilityCase)) from the declining actor to the case's CASE_MANAGER, which ledgers and broadcasts the decline. The ownership transfer offer must already exist in the actor's DataLayer (TRIG-11-005, CM-21-010, CM-21-012).
Request body (RejectCaseOwnershipTransferRequest):
| Field | Type | Required |
|---|---|---|
offer_id |
string |
Yes |
withdraw-case-ownership-transfer
POST /api/v2/actors/{actor_id}/trigger/withdraw-case-ownership-transfer
Emits an Undo of the Case Owner's own ownership-transfer proposal to the case's CASE_MANAGER, which withdraws the offer it made from it, and ledgers and broadcasts the withdrawal, if the offer is still open. offer_id names the proposal, which must already exist in the actor's DataLayer (TRIG-11-006, CM-21-015).
Request body (WithdrawCaseOwnershipTransferRequest):
| Field | Type | Required |
|---|---|---|
offer_id |
string |
Yes |
Reading path: You maintain a vulnerability tracker and want it to talk to your partners
This page is part of Build against the contract.
Before this page: