curl -s -X POST \
"https://engine.example.com/v1/approvals/holder.close-377aef663240721210eb6b60:reject" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reason": "gamma still holds FUND; close after its redemption settles"
}'// A client from OpenAPI Generator: see Build a client.
import {
ApprovalsAndOperationsApi,
Configuration,
ProblemFromJSON,
RejectApprovalBodyFromJSON,
ResponseError,
} from "./nodeasset-client";
const api = new ApprovalsAndOperationsApi(new Configuration({
basePath: "https://engine.example.com",
accessToken: process.env.TOKEN,
}));
try {
const answer = await api.rejectAction({
actionKey: "holder.close-377aef663240721210eb6b60",
rejectApprovalBody: RejectApprovalBodyFromJSON({
reason: "gamma still holds FUND; close after its redemption settles",
}),
});
console.log(answer);
} catch (e) {
if (!(e instanceof ResponseError)) throw e;
// A refusal is a problem; its type ends in the slug.
const problem = ProblemFromJSON(await e.response.json());
const slug = problem.type.split(":").pop();
console.error(e.response.status, slug, problem.detail);
}
# A client from OpenAPI Generator: see Build a client.
import os
import sys
import nodeasset_client
config = nodeasset_client.Configuration(
host="https://engine.example.com",
access_token=os.environ["TOKEN"],
)
with nodeasset_client.ApiClient(config) as client:
api = nodeasset_client.ApprovalsAndOperationsApi(client)
try:
answer = api.reject_action(
action_key="holder.close-377aef663240721210eb6b60",
reject_approval_body=nodeasset_client.RejectApprovalBody.model_validate({
"reason": "gamma still holds FUND; close after its redemption settles",
}),
)
print(answer)
except nodeasset_client.ApiException as e:
# A refusal is a problem; its type ends in the slug.
problem = nodeasset_client.Problem.from_json(e.body)
slug = problem.type.rsplit(":", 1)[-1]
print(e.status, slug, problem.detail, file=sys.stderr)
// A client from OpenAPI Generator: see Build a client.
import nodeasset.client.ApiClient;
import nodeasset.client.ApiException;
import nodeasset.client.api.ApprovalsAndOperationsApi;
import nodeasset.client.model.Problem;
import nodeasset.client.model.RejectApprovalBody;
public class RejectAction {
public static void main(String[] args) throws Exception {
ApiClient client = new ApiClient();
client.updateBaseUri("https://engine.example.com");
client.setRequestInterceptor(builder ->
builder.header("Authorization", "Bearer " + System.getenv("TOKEN")));
ApprovalsAndOperationsApi api = new ApprovalsAndOperationsApi(client);
try {
var request = ApprovalsAndOperationsApi.APIRejectActionRequest.newBuilder()
.actionKey("holder.close-377aef663240721210eb6b60")
.rejectApprovalBody(client.getObjectMapper().readValue("""
{
"reason": "gamma still holds FUND; close after its redemption settles"
}
""", RejectApprovalBody.class))
.build();
var answer = api.rejectAction(request);
System.out.println(answer);
} catch (ApiException e) {
// A refusal is a problem; its type ends in the slug.
Problem problem = client.getObjectMapper()
.readValue(e.getResponseBody(), Problem.class);
String type = problem.getType();
String slug = type.substring(type.lastIndexOf(':') + 1);
System.err.println(e.getCode() + " " + slug + " " + problem.getDetail());
}
}
}
{
"actionKey": "holder.close-377aef663240721210eb6b60",
"kind": "holder.close",
"resource": {
"kind": "holder",
"id": "gamma",
"href": "/v1/holders/gamma"
},
"maker": "operator-1",
"makerName": "Olive Park",
"makerEmail": "olive.park@venue.example",
"makerRole": "operator",
"madeAt": "2026-10-03T13:25:51.024726Z",
"state": "rejected",
"checker": "approver-1",
"checkerName": "Ann Kim",
"checkerEmail": "ann.kim@venue.example",
"checkedAt": "2026-10-03T13:25:51.030616228Z",
"operationId": null,
"reason": "gamma still holds FUND; close after its redemption settles",
"method": "POST",
"path": "/v1/holders/gamma:close",
"body": {
"holderId": "gamma"
},
"required": 1,
"signedBy": [],
"signers": []
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}Reject an action
Rejects an awaiting four-eyes action so that it never runs; its maker may withdraw its own the same way.
curl -s -X POST \
"https://engine.example.com/v1/approvals/holder.close-377aef663240721210eb6b60:reject" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reason": "gamma still holds FUND; close after its redemption settles"
}'// A client from OpenAPI Generator: see Build a client.
import {
ApprovalsAndOperationsApi,
Configuration,
ProblemFromJSON,
RejectApprovalBodyFromJSON,
ResponseError,
} from "./nodeasset-client";
const api = new ApprovalsAndOperationsApi(new Configuration({
basePath: "https://engine.example.com",
accessToken: process.env.TOKEN,
}));
try {
const answer = await api.rejectAction({
actionKey: "holder.close-377aef663240721210eb6b60",
rejectApprovalBody: RejectApprovalBodyFromJSON({
reason: "gamma still holds FUND; close after its redemption settles",
}),
});
console.log(answer);
} catch (e) {
if (!(e instanceof ResponseError)) throw e;
// A refusal is a problem; its type ends in the slug.
const problem = ProblemFromJSON(await e.response.json());
const slug = problem.type.split(":").pop();
console.error(e.response.status, slug, problem.detail);
}
# A client from OpenAPI Generator: see Build a client.
import os
import sys
import nodeasset_client
config = nodeasset_client.Configuration(
host="https://engine.example.com",
access_token=os.environ["TOKEN"],
)
with nodeasset_client.ApiClient(config) as client:
api = nodeasset_client.ApprovalsAndOperationsApi(client)
try:
answer = api.reject_action(
action_key="holder.close-377aef663240721210eb6b60",
reject_approval_body=nodeasset_client.RejectApprovalBody.model_validate({
"reason": "gamma still holds FUND; close after its redemption settles",
}),
)
print(answer)
except nodeasset_client.ApiException as e:
# A refusal is a problem; its type ends in the slug.
problem = nodeasset_client.Problem.from_json(e.body)
slug = problem.type.rsplit(":", 1)[-1]
print(e.status, slug, problem.detail, file=sys.stderr)
// A client from OpenAPI Generator: see Build a client.
import nodeasset.client.ApiClient;
import nodeasset.client.ApiException;
import nodeasset.client.api.ApprovalsAndOperationsApi;
import nodeasset.client.model.Problem;
import nodeasset.client.model.RejectApprovalBody;
public class RejectAction {
public static void main(String[] args) throws Exception {
ApiClient client = new ApiClient();
client.updateBaseUri("https://engine.example.com");
client.setRequestInterceptor(builder ->
builder.header("Authorization", "Bearer " + System.getenv("TOKEN")));
ApprovalsAndOperationsApi api = new ApprovalsAndOperationsApi(client);
try {
var request = ApprovalsAndOperationsApi.APIRejectActionRequest.newBuilder()
.actionKey("holder.close-377aef663240721210eb6b60")
.rejectApprovalBody(client.getObjectMapper().readValue("""
{
"reason": "gamma still holds FUND; close after its redemption settles"
}
""", RejectApprovalBody.class))
.build();
var answer = api.rejectAction(request);
System.out.println(answer);
} catch (ApiException e) {
// A refusal is a problem; its type ends in the slug.
Problem problem = client.getObjectMapper()
.readValue(e.getResponseBody(), Problem.class);
String type = problem.getType();
String slug = type.substring(type.lastIndexOf(':') + 1);
System.err.println(e.getCode() + " " + slug + " " + problem.getDetail());
}
}
}
{
"actionKey": "holder.close-377aef663240721210eb6b60",
"kind": "holder.close",
"resource": {
"kind": "holder",
"id": "gamma",
"href": "/v1/holders/gamma"
},
"maker": "operator-1",
"makerName": "Olive Park",
"makerEmail": "olive.park@venue.example",
"makerRole": "operator",
"madeAt": "2026-10-03T13:25:51.024726Z",
"state": "rejected",
"checker": "approver-1",
"checkerName": "Ann Kim",
"checkerEmail": "ann.kim@venue.example",
"checkedAt": "2026-10-03T13:25:51.030616228Z",
"operationId": null,
"reason": "gamma still holds FUND; close after its redemption settles",
"method": "POST",
"path": "/v1/holders/gamma:close",
"body": {
"holderId": "gamma"
},
"required": 1,
"signedBy": [],
"signers": []
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}approver, compliance, operator, risk.Authorizations
A JWT from the deployment's identity provider, whose roles claim names the caller's roles and whose holder claim names an investor's holder.
Headers
A signed request's key id, as venue.api.signing.clients configures it for the bearer's subject.
Seconds since the epoch, within venue.api.signing.window of the engine's clock, 5 minutes by default.
^[0-9]+$At least 16 random bytes in base64url, never reused within twice the window.
22 - 128^[A-Za-z0-9_-]+={0,2}$The base64 HMAC-SHA256, under the key's secret, of the method, the path and query, the timestamp, the nonce and the body's SHA-256.
Your id for this request, 1 to 128 printable characters, repeated in the answer; absent, the engine makes one.
128^[\x21-\x7E]+$A W3C trace context, which the engine joins and passes on.
^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$Path Parameters
The four-eyes action's key, as its maker's call and GET /v1/approvals name it.
Body
The rejection's reason.
Why, 1 to 512 characters.
Response
The action, rejected.
A four-eyes action, with the request it is and where it stands.
The four-eyes action's key.
The operation kind the action runs as.
instrument.record, policy.set, admission-consent.propose, instrument.pause, holder.register, holder.onboard, holder.close, holder.register-successor, holder.set-attributes, admission.offer, admission.withdraw, accepted-terms.accept, subscription.claim, subscription.withdraw, subscription.deliver, subscription.settle, subscription.release, primary-market.propose, redemption.claim, redemption.withdraw, redemption.release, redemption.settle, dealing-cycle.open, dealing-cycle.settle, dealing-cycle.release, standing-settlement.open, standing-settlement.settle, standing-settlement.pause, standing-settlement.resume, standing-settlement.close, reserve.propose, reserve.close, lock-agreement.propose, lock-agreement.release, mint.start, mint.cancel, reserve-redemption.start, reserve-redemption.cancel, reserve-report.create, amendment.propose, amendment.withdraw, provision-settlement.propose, distribution.execute, distribution.roll, standing-approval.grant, standing-approval.revoke, holder.restrict, holder.restrict-batch, restriction.lift, issuer-powers-agreement.propose, issuer-powers-consent.offer, holder.force-transfer, holder.recover, instrument.force-transfer, instrument.recover, hold.release, external-account.map, webhook.register, webhook.remove, webhook.test The record it acts on, and, once it succeeds, the record it created or changed.
Show child attributes
Show child attributes
Who made the action, by sub.
The name claim of the maker's bearer; null where it carried none.
The email claim of the maker's bearer; null where it carried none.
The role the maker acted in.
operator, approver, risk, compliance, auditor, investor, app, monitor, feed, registrar When the maker made the action.
Where the action stands.
awaiting, approved, rejected Who decided it, the approver, or on a rejection the approver or the maker withdrawing it; null while it awaits.
The name claim of the checker's bearer; null while it awaits, or where it carried none.
The email claim of the checker's bearer; null while it awaits, or where it carried none.
When the action was decided; null while it awaits.
The operation the approved action ran as.
Why it was rejected.
The request's method.
The concrete path the maker sent.
The request the action runs with, as its route opened it; an approval by key sends the maker's own body.
How many distinct approvers the action needs.
The approvers who have signed it so far; all of them once approved.
Each sign-off so far, in order: who signed, with the name and email claims of their bearer, and when.
Show child attributes
Show child attributes

