# Intent request structure

Use this page to understand the request body structure for intent proposals, dry runs, and signatures. For an introduction to the concept of intents, see [Intents and approvals](/products/custody/governance/intents).

An **intent** is a request to execute an action, which executes once it has the approvals its matching policy requires. For the full execution lifecycle, see [Intents and approvals](/products/custody/governance/intents).

The submitter of an intent defines, in particular, the following fields:

- `payload`, which sets the `type` of the intent and the details of the operation to process;
- `expiryAt`, which sets an expiration time to the intent;
- `targetDomainId`, which sets the domain in which to execute the intent (either in the current domain or within a descendant domain);
- `type`, which defines whether the request is an original user-signed submission (`Propose`), a system-signed submission (`SystemSigned`), an intention to approve an existing intent (`Approve`), or an intention to reject an existing intent (`Reject`).


There exist four intent types for most entities in the system, as prefixed by:

- **Create** to create an entity of a given type;
- **Update** to update the definition of an entity;
- **Lock** to lock an entity;
- **Unlock** to unlock an entity.


Exceptions exist, such as for the release of quarantined **transfers**, which has its dedicated intent called **ReleaseQuarantinedTransfers**.

A generic intent, named **NotarizeData**, allows the submission of intents not related to internal processes of Ripple Custody. Such **intents** may be used to trigger external effects to extend the capabilities of the system, such as to initiate fiat payment orders or trading orders.

## Structure of an intent

There are three request body types covered on this page:

- User-signed proposal request body: Request body to propose a new intent with a user signature.
- System-signed proposal request body: API-only request body to propose an intent without a client-side payload signature.
- Dry run and signature request body: Request body to perform a dry run of a user-signed intent proposal, or add a signature to the user-signed proposal request body.


Both types include the same set of standard fields and fields that are specific to the intent type.

You can see an example of each request body type in the examples below.

### Standard proposal fields

The data you need to specify in your request is as follows:

| Field | User-signed proposal | System-signed proposal | Description |
|  --- | --- | --- | --- |
| `request.type` | `Propose` | `SystemSigned` | Discriminator for the proposal body. |
| `request.author.id` | Required | Not used | User ID of the intent submitter. |
| `request.author.domainId` | Required | Not used | Domain ID of the user submitter. For intents that must be submitted in a specific domain, this ID must correspond to the required domain. |
| `request.expiryAt` | Required | Required | Expiry date for the intent, expressed as an ISO timestamp. |
| `request.targetDomainId` | Required | Required | Target domain where the intent is to be executed. |
| `request.id` | Required | Required | A new ID for the intent in valid UUID format. |
| `request.payload` | Required | Required | Specific details for the intent type. For more information, see [Specific fields of an intent](#specific-fields-of-an-intent). |
| `request.description` | Optional | Optional | Human-readable description. |
| `request.customProperties` | Required | Required | Custom metadata. Use `{}` when empty. |
| `signature` | Required | Not used | Top-level cryptographic signature generated with the user submitter's private key. |


### Specific fields of an intent

All the properties that are specific to the type of intent being created (create a domain, update some user details, and so on) are inside the `payload` block.

You can see examples of `payload` blocks in the following sections:

- [Manage vaults](/products/custody/identity-and-access/vault-management/manage-vaults)
- [Manage accounts with the API](/products/custody/accounts-and-assets/accounts/manage-accounts-api)
- [Manage endpoints](/products/custody/accounts-and-assets/endpoints/manage-endpoints)
- [Manage tokens with the API](/products/custody/accounts-and-assets/tokenization/token-management/api)
- [Send assets with the API](/products/custody/transactions/send-and-receive/send-assets-api)


### User-signed proposal request body

The following example shows the request body needed to propose an endpoint creation intent:


```json User-signed proposal request body
{
    "request": {
        "author": {
            "id": "9b672a12-37d1-456a-8d35-57426090a156",
            "domainId": "9067d363-6411-498b-a32b-15d230a86706"
        },
        "expiryAt": "2022-11-19T16:00:01.621Z",
        "targetDomainId": "9067d363-6411-498b-a32b-15d230a86706",
        "id": "00baa536-421e-11ee-be56-0242ac120002",
        "payload": {
            "id": "202c33d0-421e-11ee-be56-0242ac120002",
            "address": "0xD135295cC7562593995202638b8509ba3d108e1",
            "trustScore": 100,
            "ledgerId": "avalanche-chain-testnet-fuji",
            "alias": "New endpoint",
            "lock": "Unlocked",
            "customProperties": {},
            "type": "v0_CreateEndpoint"
        },
        "description": "Test endpoint create",
        "type": "Propose"
    },
    "signature": "<SIGNATURE>"
}
```

### System-signed proposal request body

System-signed proposal submission is available only through the API. The caller authenticates with a bearer token. The request body does not include `request.author` or a top-level `signature`.


```json System-signed proposal request body
{
    "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": {}
    }
}
```

System-signed proposals are matched by policies that use `intentOrigin: "SystemSigned"`. If no matching policy applies, the intent cannot execute. Approvals and rejections still use user-signed request bodies.

Before submitting this request body, the active Gateway system signing public key must be registered in Notary, `NOTARY_SYSTEM_SIGNED_INTENTS_ENABLED` must be set to `enabled: true`, and the target domain must have a matching `SystemSigned` policy. For the full setup sequence, see [System-signed intent configuration](/products/custody/deployment/reference/system-signed-intents).

### Dry run and signature request body

The following example shows the subset of the [User-signed proposal request body](#user-signed-proposal-request-body) needed to:

- Perform a dry run of an endpoint creation intent.
- Generate the cryptographic signature for a user-signed endpoint creation intent proposal.


The dry-run API request body uses the user-signed shape and includes an `author`. The OpenAPI specification does not define a system-signed dry-run request body.


```json Dry run and signature request body
{
    "author": {
        "id": "9b672a12-37d1-456a-8d35-57426090a156",
        "domainId": "9067d363-6411-498b-a32b-15d230a86706"
    },
    "expiryAt": "2022-11-19T16:00:01.621Z",
    "targetDomainId": "9067d363-6411-498b-a32b-15d230a86706",
    "id": "00baa536-421e-11ee-be56-0242ac120002",
    "payload": {
        "id": "202c33d0-421e-11ee-be56-0242ac120002",
        "address": "0xD135295cC7562593995202638b8509ba3d108e1",
        "trustScore": 100,
        "ledgerId": "avalanche-chain-testnet-fuji",
        "alias": "New endpoint",
        "lock": "Unlocked",
        "customProperties": {},
        "type": "v0_CreateEndpoint"
    },
    "description": "Test endpoint create",
    "type": "Propose"
}
```