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.
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.
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.jsonThe 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.
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.
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.
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. |
| 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.