Skip to main content
POST
SDK — approve a proposal

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

environmentId
string
required

ID of the environment

Required string length: 36
Pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
Example:

"95b11417-f18f-457f-8804-68e361f9164f"

businessAccountId
string
required

ID of the business account

Required string length: 36
Pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
Example:

"95b11417-f18f-457f-8804-68e361f9164f"

proposalId
string
required

ID of the business account proposal

Required string length: 36
Pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
Example:

"95b11417-f18f-457f-8804-68e361f9164f"

Body

application/json

SDK approveProposal body. The signature is over the proposal's stored intent together with approvedAt, produced by the approver's session key — which never leaves their device, so approving cannot be done on their behalf.

approvedAt
string<date-time>
required

Inside the signed payload, so only the approver can set their own.

signature
string
required

Hex-encoded signature over the intent and approvedAt.

Response

Approval recorded; the proposal with its current approvals

A governed mutation waiting on consent. Untrusted workflow state: it records what was proposed and who has signed, and the enclave verifies every signature when the proposal is executed. The signature is over intent as stored, so an approver must sign these exact bytes — re-deriving the intent would produce a different intentId and invalidate the approvals already collected.

id
string<uuid>
required
businessAccountId
string<uuid>
required
actionType
enum<string>
required

A business-account mutation that an approval requirement can gate.

Available options:
addMember,
removeMember,
updateMemberRole,
transferOwnership,
createWallet,
linkWallet,
removeWallet,
addSignerToWallet,
removeSignerFromWallet,
setGovernance,
defineRole,
deleteRole
status
enum<string>
required

Lifecycle of a governed mutation awaiting approvals. Only pending accepts approvals; the other three are terminal.

Available options:
pending,
executed,
vetoed,
expired
initiatorUserId
string<uuid>
required

Who proposed it. They can never approve their own intent, so they are never counted toward a requirement.

intent
object
required

The initiator's proposal, signed with their session key. Built by the API, not the client — sign these exact bytes verbatim, because re-serializing can change them and invalidate the signature. autoExecute is inside the signed bytes, so an approver consents to it and nothing can flip it afterwards.

completeBy
string<date-time>
required

The one deadline for the whole proposal, derived from the signed intent's createdAt. Past it the proposal accepts no further approvals AND can no longer be executed.

createdAt
string<date-time>
required
approvals
object[]
required
consumedAt
string<date-time> | null

When it left pending; null while still open.

autoExecute
boolean

Whether this applies as soon as its quorum is met, or waits for an explicit execute. A copy of the flag inside the signed intent, which is the authority. An approver needs this to know whether their approval is the one that lands the change.

subjects
object[]

The users this change is about, resolved for display — the member being added, the signer being removed, the new owner. Empty for a change that names no user, such as setGovernance.

approvalRequirements
object[]

Every governance rule matching this proposal, with how close each is. Do NOT derive progress from approvals — that counts rows, including approvers outside a rule's pool and approvers demoted since they signed. Absent means the tally is unknown (not fetched, or no longer pending); an empty array means nothing is outstanding. Treat the two differently.

Last modified on September 9, 2026