Use this page for day-to-day intent submission, review, approval, rejection, dry runs, and state checks. For the concept, see Intents and approvals.
| Action | UI procedure | API procedure |
|---|---|---|
| Request a change | Request a change in the UI | Submit an intent with the API |
| Submit a system-signed proposal | Not available in the UI. | Submit a system-signed intent with the API |
| Dry run an intent | Use the API procedure. | Dry run an intent with the API |
| Approve or reject an intent | Approve or reject an intent in the UI | Approve or reject an intent with the API |
| Check request, intent, entity, transaction state, and remaining approvers | Check state in the UI | Check state with the API |
During initial system setup, the POST /v1/genesis API operation creates the initial environment and entities without authentication or governance. After that initial setup, changes to system data follow the intent workflow.
- Dry run the payload when you are using the API or testing a high-risk payload.
- Submit the intent. Most submissions are user-signed. API service callers can submit system-signed proposals when the deployment and policies allow it.
- Review the pending intent.
- Approve or reject.
- Check request, intent, entity, and transaction state.
Every change you make to system data in the UI creates an intent. For example, creating a domain, creating a user, registering an endpoint, or sending assets all follow the same high-level pattern:
- Navigate to the relevant UI area.
- Enter the change details.
- Click Submit for approval.
- Sign the operation with the Ripple Custody: Auth & Sign app. For signing instructions, see Sign UI operations.
- Track the intent until it is approved, rejected, expired, or executed.
For UI and other user-signed submissions, the submitter of the intent acts as the first approver. If the selected policy includes an approval workflow that does not match the submitter's user role, the intent fails.
Dry runs simulate user-signed intent submission so you can understand whether a payload is valid before proposing and signing it.
Use dry runs for:
- Policy, domain, user, and user role-assignment changes.
- High-risk or complex transactions.
- Payloads where condition or workflow behavior is uncertain.
- Payloads that depend on ledger-specific validation, balances, destinations, or fees.
To perform a dry run:
- Prepare the request body in the format shown in Dry run and signature request body.
- Call the Perform a dry run operation.
- Review the
successanderrorsfields. For transaction intents, inspectresultandestimate: their failure variants include ahintfield.
The SDK examples on this page assume a configured client. To configure one, see Integrate via SDK. The following examples perform a dry run with the API and with each SDK:
curl -X POST "${CUSTODY_API_URL}/v1/intents/dry-run" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Content-Type: application/json" \
-d @intent-dry-run.jsonThe dry-run request body uses the user-signed proposal shape and includes an author. The API specification does not define a separate system-signed dry-run body.
The Propose an intent operation is the entry point for state mutation API requests. This procedure describes the standard user-signed proposal flow.
To submit an intent:
- Prepare the intent request object with the author, expiry, target domain, intent ID, payload, description, custom properties, and
type: "Propose". - Canonicalize and sign the request object. For signing details, see Authenticate API requests.
- Create the full request body with the signed
requestobject andsignature. - Call Propose an intent with the signed request body.
With an SDK, each method that changes state performs steps 1 to 4 and returns a pending intent. The pending intent's wait methods poll the request state until Ripple Custody (Vault) accepts the request. They then poll the intent state until the intent reaches a final status. The following examples submit a transfer order with the API and with each SDK:
curl -X POST "${CUSTODY_API_URL}/v1/intents" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Content-Type: application/json" \
-H "requestId: ${REQUEST_ID}" \
-d @signed-intent.jsonFor a complete program, see example 13 (create transfer order). To get the examples, see Examples.
For more about pending intents and wait methods, see SDK intents.
The requestId header is optional but recommended for traceability. You can use it to check request state.
The operation returns 202 Accepted with an intent response when the request is accepted for asynchronous processing. This response means the workflow is scheduled. It does not mean the intent has executed or that the resulting entity or transaction state has changed.
System-signed intent submission is for service callers that are allowed to propose specific intent types without sending a client-side payload signature. The request is still authenticated with a bearer token, signed internally by the platform, and governed by policies.
The Ripple Custody (Vault) SDKs don't submit system-signed proposals. Use the API for this flow.
Before using this flow, confirm that:
- System-signed intent configuration is available for the deployment.
- The active Gateway system signing public key is registered in Notary. To discover the active public key, call
GET /v1/system-signing/info. For more information, see System signing info endpoint. NOTARY_SYSTEM_SIGNED_INTENTS_ENABLEDis set toenabled: true.- The service caller can obtain a bearer token accepted by the API.
- A policy with
intentOrigin: "SystemSigned"matches the target domain, intent type, and service caller.
System-signed intent configuration is enabled by default at deployment level. This does not activate system-signed traffic. Until key registration, the runtime system property, and matching policies are in place, system-signed proposals fail closed.
Prepare a request body with request.type: "SystemSigned". Do not include request.author or a top-level signature.
{
"request": {
"type": "SystemSigned",
"targetDomainId": "9067d363-6411-498b-a32b-15d230a86706",
"id": "00baa536-421e-11ee-be56-0242ac120002",
"expiryAt": "2026-06-30T15:30:00.000Z",
"payload": {
"type": "v0_CreateTransactionOrder",
"...": "payload-specific fields"
},
"description": "Service-submitted transaction order",
"customProperties": {}
}
}Submit the request:
curl -X POST "${CUSTODY_API_URL}/v1/intents" \
-H "Authorization: Bearer ${SERVICE_JWT_TOKEN}" \
-H "Content-Type: application/json" \
-H "requestId: ${REQUEST_ID}" \
-d @system-signed-intent.jsonThe response uses the same 202 Accepted response shape as user-signed proposal submission. When you retrieve the intent or request state, service-authored records identify the submitter with author.subject or requester.subject. For how these relate to context.submitter.subject in policy conditions, see Service-caller identity.
System-signed submission applies to proposals only. The service submitter does not count as a user approval. If the selected system-signed policy includes a workflow, user-signed approvers must satisfy it.
You can approve or reject intents that are relevant for your user. The intents you can approve or reject depend on your user role and the policies that apply in the domain hierarchy.
To approve or reject an intent:
- Navigate to Intents.
- Select the Waiting for decision tab.
- Select the arrow next to the intent's status to open the decision workflow panel.
- Review the intent details, selected policy, approval workflow, and any compliance or incident notes.
- Scroll to the end of the workflow and select Approve or Reject.
- Enter the reason. The reason is mandatory for rejections and optional for approvals.
- Sign the operation with the Ripple Custody: Auth & Sign app.
If you approve the intent, it continues through the workflow. When all required steps are complete, the intent can execute. If you reject the intent, the status changes to Rejected.
To approve or reject an intent with the API:
- Retrieve the intent details with List intents or Get intent.
- Prepare the approval or rejection request body. Use the intent ID and the
proposalSignaturefrom the intent details. - Canonicalize and sign the request object. For signing details, see Authenticate API requests.
- Call Approve intent or Reject intent.
Approval and rejection API calls also return 202 Accepted when the signed decision is accepted for asynchronous processing. Check the request or intent state to confirm whether the workflow processed the decision successfully.
With an SDK, you approve or reject by intent ID. The SDK fetches the proposalSignature (the Java SDK takes it as an argument), then builds, signs, and submits the decision. If you hold the pending intent from your own proposal, you can also call its approve or reject method.
The following examples approve and reject an intent with the API and with each SDK:
Approve example:
{
"request": {
"author": {
"id": "828b554c-c9c9-11eb-a79b-dcfb48cfb3cb",
"domainId": "455ad43e-cdd9-11eb-8465-dcfb48cfb3cb"
},
"targetDomainId": "455ad43e-cdd9-11eb-8465-dcfb48cfb3cb",
"intentId": "846b5c3c-27e3-4146-ab18-ce6732624d35",
"proposalSignature": "<PROPOSAL_SIGNATURE>",
"approvalReason": "Approved after review",
"type": "Approve"
},
"signature": "<APPROVAL_SIGNATURE>"
}curl -X POST "${CUSTODY_API_URL}/v1/intents/approve" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Content-Type: application/json" \
-d @signed-approval.jsonFor rejection, use type: "Reject" and include rejectReason.
For a complete program, see example 20 (governance intents). To get the examples, see Examples.
Intent workflows have several state checks:
| Check | UI procedure |
|---|---|
| Request state | Use request lists and status messages in the UI. |
| Intent state | Navigate to Intents and review the intent status and workflow details. |
| Remaining approvers | Review the approval workflow in the UI. |
| Entity state | Open the created or updated entity in the relevant UI area. |
| Transaction state | View transaction, transfer, and order tabs for the account. |
The following examples check each state with the API and with each SDK:
| Check | API procedure |
|---|---|
| Request state | Call Get request state with the requestId. |
| Intent state | Call Get intent with the intent ID. |
| Remaining approvers | Call Get remaining users. |
| Entity state | Call the relevant entity API, such as Get current user, Get domain details, or Get account details. |
| Transaction state | Use View transactions with the API. |
Any authorized rejection stops the workflow. Expired intents do not execute and must be recreated if the change is still needed.
For service-authored records, List intents supports filtering with details.author.subject.
Before approving an intent, check:
- Target domain.
- Intent type.
- Payload.
- Selected policy.
- Required workflow.
- Remaining approvers.
- Expiry time.
- Compliance or incident notes.
For payload fields, see Intent reference.