Skip to content

Use this page for day-to-day intent submission, review, approval, rejection, dry runs, and state checks. For the concept, see Intents and approvals.

Intent actions

ActionUI procedureAPI procedure
Request a changeRequest a change in the UISubmit an intent with the API
Submit a system-signed proposalNot available in the UI.Submit a system-signed intent with the API
Dry run an intentUse the API procedure.Dry run an intent with the API
Approve or reject an intentApprove or reject an intent in the UIApprove or reject an intent with the API
Check request, intent, entity, transaction state, and remaining approversCheck state in the UICheck state with the API

Intent workflow

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.

  1. Dry run the payload when you are using the API or testing a high-risk payload.
  2. Submit the intent. Most submissions are user-signed. API service callers can submit system-signed proposals when the deployment and policies allow it.
  3. Review the pending intent.
  4. Approve or reject.
  5. Check request, intent, entity, and transaction state.

Request a change in the UI

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:

  1. Navigate to the relevant UI area.
  2. Enter the change details.
  3. Click Submit for approval.
  4. Sign the operation with the Ripple Custody: Auth & Sign app. For signing instructions, see Sign UI operations.
  5. 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 run an intent with the API

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:

  1. Prepare the request body in the format shown in Dry run and signature request body.
  2. Call the Perform a dry run operation.
  3. Review the success and errors fields. For transaction intents, inspect result and estimate: their failure variants include a hint field.
curl -X POST "${CUSTODY_API_URL}/v1/intents/dry-run" \
  -H "Authorization: Bearer ${JWT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d @intent-dry-run.json

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

Submit an intent with the API

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:

  1. Prepare the intent request object with the author, expiry, target domain, intent ID, payload, description, custom properties, and type: "Propose".
  2. Canonicalize and sign the request object. For signing details, see Authenticate API requests.
  3. Create the full request body with the signed request object and signature.
  4. 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.json

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.

Submit a system-signed intent with the API

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_ENABLED is set to enabled: 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.json

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

Approvals and rejections stay user-signed

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.

Approve or reject an intent in the UI

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:

  1. Navigate to Intents.
  2. Select the Waiting for decision tab.
  3. Select the arrow next to the intent's status to open the decision workflow panel.
  4. Review the intent details, selected policy, approval workflow, and any compliance or incident notes.
  5. Scroll to the end of the workflow and select Approve or Reject.
  6. Enter the reason. The reason is mandatory for rejections and optional for approvals.
  7. 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.

Approve or reject an intent with the API

To approve or reject an intent with the API:

  1. Retrieve the intent details with List intents or Get intent.
  2. Prepare the approval or rejection request body. Use the intent ID and the proposalSignature from the intent details.
  3. Canonicalize and sign the request object. For signing details, see Authenticate API requests.
  4. 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.json

For rejection, use type: "Reject" and include rejectReason.

Check state

Intent workflows have several state checks:

Check state in the UI

CheckUI procedure
Request stateUse request lists and status messages in the UI.
Intent stateNavigate to Intents and review the intent status and workflow details.
Remaining approversReview the approval workflow in the UI.
Entity stateOpen the created or updated entity in the relevant UI area.
Transaction stateView transaction, transfer, and order tabs for the account.

Check state with the API

CheckAPI procedure
Request stateCall Get request state with the requestId.
Intent stateCall Get intent with the intent ID.
Remaining approversCall Get remaining users.
Entity stateCall the relevant entity API, such as Get current user, Get domain details, or Get account details.
Transaction stateUse 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.

Review checklist

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.