# Ripple Custody API

Ripple Custody exposes a complete set of API operations to administer and operate the system programmatically. The below entities are at the core of the system:
- **intents** represent requests to execute an action within the system that may eventually be executed if fully approved;
- **domains** define segregated sets of entities (e.g., users, policies and accounts) with guaranteed isolation from each other;
- **users** are human or technical consumers of the service;
- **policies** are operational rules defining the required (multi-)approval workflow for the execution of particular intents;
- **vaults** are logical key stores responsible for the building and signing of outgoing transactions;
- **accounts** are particular sets of addresses within a vault for which balance(s) and transactions are tracked;
- **transaction orders** are orders to transfer digital assets or request an operation on the ledger;
- **transactions** are incoming or outgoing ledger transactions that have been detected on the ledger or shall be broadcast;
- **transfers** are the financial representation of their corresponding **transactions**;
- **endpoints** associate ledger addresses with human-readable aliases to keep track of whitelisted and blacklisted addresses;
- **ledgers** are accounting systems that are supported and tracked;
- **tickers** define the detected currencies and their respective symbols and parameters;
- **events** are the notification payloads generated through user actions, system signals, and ledger updates.
- **requests** allow to follow the progress of a user request and identify a possible failure.

Because the security of digital assets is paramount, Ripple Custody leverages multiple security protocols ensuring a proper management of the keys, of the signature process, of user authentication, of the application of governance policies and overall of data integrity system-wide. Notably, 
- every request to mutate the system, as modelled through an **intent**, must be signed by all parties involved, such that an end-to-end secure link is set between the API consumer and the core of Ripple Custody;
- every request to mutate the system is subject to programmable **policies** that regulate the exact quorum of users being authorized to approve and execute the **intent**;
- every critical entity is protected by a data integrity protocol. Entities are versioned and stored as part of a Merkle tree whose root is signed for any mutation of the data. Any data tampering attempt at the database level or in transit is identified and fails at runtime. All such protected entites are wrapped into a `data` envelope and augmented with a `signature` field at the API level to allow a validation of the data integrity from the outside the system. This is particularly relevant to validate, for instance, the integrity of deposit addresses of a given account.

Most entity types rely on a common pattern exposing the following fields:
 - `id`: a user-defined unique identifier (UUID); once defined, an id cannot be modified
 - `metadata.revision`: a system-enforced revision number set to 1 for the creation of the entity, and incremented at every entity update
 - `metadata.description`: an optional user-defined description of the entity
 - `metadata.createdAt`: a system-enforced timestamp marking the creation time of the entity
 - `metadata.createdBy`: a system-enforced reference to the creator of the entity
 - `metadata.lastModifiedAt`: a system-enforced timestamp marking the last update time of the entity
 - `metadata.lastModifiedBy`: a system-enforced reference to the last updater of the entity
 - `metadata.customProperties`: a user-defined key-value store to attach arbitrary data to the entity, such as a correlation identifier; customProperties are part of the evaluation context of policies conditions and may be used to trigger particular approval workflows

Together, `id` and `metadata.revision` are the basis of the anti-replay model in Ripple Custody.

Most entities also expose a `lock` flag to make the entity read-only and prevent its use during runtime:
- `lock`: lock status of an entity, which may be `Locked` or `Unlocked`; an `Unlocked` entity inherits the lock of its hierarchical parent and a `Locked` entity (with its dependent entities) may not be used at runtime.

Locking a **domain** will lock all its inner entities as well as subdomains; locking a **user** will prevent it from submitting any request to the system or to access the service; locking a **policy** will ignore it entirely in the context of the policy selection; locking a **vault** will lock all its related **accounts**; locking an **account** will prevent the execution of transactional operations; locking an **endpoint** will prevent its use as a transaction order destination.

For requests returning a list of entities, pagination is enabled by default. The request may include a `limit` parameter to properly quantify the size of the response, a `startingAfter` parameter to define the anchor point, `sortBy` to define a possible sorting property, `sortOrder` to specify the direction of the sorting (resp. "ASC", "DESC") and possibly filtering criterions that may be entity-specific.

Responses are packaged within a list of `items` and a pointer to the next page is exposed as property `nextStartingAfter`.




## Servers

```
https://{INSTANCE_URL}
```

## Security

### httpAuth

Type: http
Scheme: bearer

## Download OpenAPI description

[Ripple Custody API](https://docs.ripple.com/_bundle/products/custody/@v1.15/api/reference/openapi.yaml)

## Genesis

The **genesis** is the process by which a Ripple Custody environment is initialized. Upon system deployment, it is mandatory to define a **primary domain**, together with a suitable set of **users** and **policies**, such that the system can be operated using regular workflows. At minimum, one user and one policy must be defined, but a whole array of users and policies can be defined in order to render the Ripple Custody bootstrapping an atomic process.

The input request body contains two sections, namely the `rootDomainSetup` and the `cryptoSetup`. The former is akin to a regular new domain creation payload, while the latter is used to select the cryptographic algorithms to be used by the system.

Of particular importance, at genesis level, is the setting up of a **breakglass**, i.e., a protection mechanism against possible mis-usage of the policy engine that will allow to restore the system in case of wrong user manipulation. Enabling this feature is achieved by setting the property `governingStrategy` to `CoerceDescendants`. More information on this feature can be found in the developer documentation.

Calls to the genesis route are not authenticated, since the system has no active users at this stage.

Running Genesis on a new installation includes two properties in the `GenesisSucceeded` notary event:
- `genesis`: a data structure holding the notary signed original genesis payload
- `createdEntitiesReferences`: with key information on the data created

### Run the genesis

 - [POST /v1/genesis](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/genesis/rungenesis.md)

## Domains

A **domain** defines a segregated set of entities (e.g., users, policies and accounts) with guaranteed isolation from each other. It also maintains the read access permissions of the domain users.

**Domains** are organized as part of a domain hierarchy, or tree: at the top of the hierarchy stands the root domain, which is defined at system genesis with the first **users** and **policies**. From the root domain down, subdomains can be created. The hierarchical structure ensures that any **intent** processed by the system must satisfy the **policies** of the **domain** in which the intent is to be executed, but also of all ancestors **domains** up to the root.

**Domain** segregation may be used to isolate the operations of different departments, subsidiaries, or possibly clients, of the custodian and provide them with the ability to define their own respective users, policies, and accounts independently.

The locking of a **domain** prevents the execution of any **intent** within the **domain** or any of its subdomains.

### Get domain details

 - [GET /v1/domains/{domainId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/domains/getdomain.md)

### List domains

 - [GET /v1/domains](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/domains/getdomains.md)

## Vaults

A **vault** is a component that maintains secret key material and is responsible for the creation and signing process of outgoing ledger transactions.

A **vault** executes **transaction orders** once they are fully approved and delivers the signed ledger **transaction** to the system for broadcast. A single instance of Ripple Custody can hold multiple **vaults**, which may provide complementary features (e.g., various distributed ledger protocols), key stores (e.g., different hardware vendors or multi-party computation-based algorithms), or key isolation (e.g., connected, or air-gapped). For example, a system can leverage a hot vault (for hot accounts) and an air-gapped vault (for cold accounts). **Accounts** within the system are associated with specific vaults.

The registration of the public key of a vault, `publicKey`, allows the system to verify any information returned by the vault.

The locking of a **vault** prevents the execution of any **transaction order** related to the specific **vault**.

### List vaults

 - [GET /v1/vaults](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/vaults/getvaults.md)

### Get vault details

 - [GET /v1/vaults/{vaultId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/vaults/getvault.md)

### Export prepared operations

 - [GET /v1/vaults/{vaultId}/operations/prepared](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/vaults/paths/~1v1~1vaults~1%7Bvaultid%7D~1operations~1prepared/get.md): Export prepared operations

### Import signed operations

 - [POST /v1/vaults/operations/signed](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/vaults/paths/~1v1~1vaults~1operations~1signed/post.md): Import signed operations

## Ledgers

A **ledger** is an accounting system, such as a blockchain, that is supported and tracked.

A **ledger** is defined by its `parameters`, which describe its protocol and configuration. For any supported protocol, multiple ledgers instances may be registered. This allows derivative ledgers, such as testnets, forks, or permissioned instances to be connected to Ripple Custody natively. 

### List ledgers

 - [GET /v1/ledgers](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/ledgers/getledgers.md)

### Get ledger details

 - [GET /v1/ledgers/{ledgerId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/ledgers/getledger.md)

### Get ledger's fee details

 - [GET /v1/ledgers/{ledgerId}/fees](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/ledgers/getledgerfees.md)

### [Ethereum] Process contract call

 - [POST /v1/ledgers/{ledgerId}/ethereum/call](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/ledgers/processethereumcontractcall.md)

## Tickers

A **ticker** defines a detected currency and its respective symbol, number and parameters.

In particular, the number of `decimals` of a particular ticker is critical to the proper encoding of transfer amounts.

### List tickers

 - [GET /v1/tickers](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/tickers/gettickers.md)

### Get ticker details

 - [GET /v1/tickers/{tickerId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/tickers/getticker.md)

## Accounts

An **account** tracks the balance(s) and transactions history of a data source. In the context of a distributed ledger, it relies on a set of keys and addresses provided by its **vault**.

For multi-address ledger protocols, accounts may generate and track multiple separate addresses transparently. For multi-currency protocols, a single account may have multiple balances corresponding to each respective asset owned by the **account**.

An **account** ensures the quarantine of all incoming transfers, such that their release is suject to a formal **policy**. It also manages balance reserves to ensure fully approved transaction orders become executable with little delay.

The locking of an **account** prevents the execution of any **transaction order** related to the specific **account**, as well as the release of quarantined incoming **transfers**.

### List accounts

 - [GET /v1/domains/{domainId}/accounts](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/getaccounts.md)

### Get account details

 - [GET /v1/domains/{domainId}/accounts/{accountId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/getaccount.md)

### Retrieve all generated addresses

 - [GET /v1/domains/{domainId}/accounts/{accountId}/addresses](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/getaddresses.md)

### Generate new account external address

 - [POST /v1/domains/{domainId}/accounts/{accountId}/addresses/{ledgerId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/generatenewexternaladdress.md)

### Retrieve account address

 - [GET /v1/domains/{domainId}/accounts/{accountId}/addresses/{accountAddressId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/getaccountaddress.md)

### Get account balances

 - [GET /v1/domains/{domainId}/accounts/{accountId}/balances](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/getaccountbalances.md)

### Update account balances forcefully

 - [POST /v1/domains/{domainId}/accounts/{accountId}/balances/refresh](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/forceupdateaccountbalances.md)

### List manifests

 - [GET /v1/domains/{domainId}/accounts/{accountId}/manifests](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/getmanifests.md)

### Get manifest details

 - [GET /v1/domains/{domainId}/accounts/{accountId}/manifests/{manifestId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/getmanifest.md)

### Generate new account external address (deprecated)

 - [POST /v1/domains/{domainId}/accounts/{accountId}/addresses](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/generatenewexternaladdressdeprecated.md)

### Retrieve latest external address (deprecated)

 - [GET /v1/domains/{domainId}/accounts/{accountId}/addresses/latest](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/accounts/getlatestaddress.md)

## External accounts

**External account** API operations are used to connect to a third party custodian, typically a trading venue, to instruct trading orders directly from Ripple Custody. The following calls allow to setup a connection with an external provider, list the external accounts and their balances.

### Connect an external account provider

 - [POST /v1/domains/{domainId}/external-accounts/providers](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1providers/post.md): Connect an external account provider

### List external account provider connections

 - [GET /v1/domains/{domainId}/external-accounts/providers](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1providers/get.md): List external account provider connections

### Update an external account provider connection

 - [POST /v1/domains/{domainId}/external-accounts/providers/{connectionId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1providers~1%7Bconnectionid%7D/post.md): Update an external account provider connection

### Get external account provider connections

 - [GET /v1/domains/{domainId}/external-accounts/providers/{connectionId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1providers~1%7Bconnectionid%7D/get.md): Get external account provider connections

### Disconnect an external account provider

 - [DELETE /v1/domains/{domainId}/external-accounts/providers/{connectionId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1providers~1%7Bconnectionid%7D/delete.md): Disconnect an external account provider

### List external accounts

 - [GET /v1/domains/{domainId}/external-accounts](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts/get.md): List external accounts

### Get external account details

 - [GET /v1/domains/{domainId}/external-accounts/{externalAccountId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1%7Bexternalaccountid%7D/get.md): Get external account details

### Get external account balances

 - [GET /v1/domains/{domainId}/external-accounts/{externalAccountId}/balances](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1%7Bexternalaccountid%7D~1balances/get.md): Get external account balances

### Retrieve latest external address

 - [GET /v1/domains/{domainId}/external-accounts/{externalAccountId}/addresses/latest](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1%7Bexternalaccountid%7D~1addresses~1latest/get.md): Retrieve latest external address

### Retrieve all generated addresses

 - [GET /v1/domains/{domainId}/external-accounts/{externalAccountId}/addresses](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1%7Bexternalaccountid%7D~1addresses/get.md): Retrieve all generated addresses

### Generate new account external address

 - [POST /v1/domains/{domainId}/external-accounts/{externalAccountId}/addresses](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1%7Bexternalaccountid%7D~1addresses/post.md): Generate new account external address

### Retrieve account external address

 - [GET /v1/domains/{domainId}/external-accounts/{externalAccountId}/addresses/{externalAccountAddressId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-accounts/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1%7Bexternalaccountid%7D~1addresses~1%7Bexternalaccountaddressid%7D/get.md): Retrieve account external address

## Endpoints

An **endpoint** associates ledger addresses with human-readable aliases to keep track of whitelisted and blacklisted addresses. It is also used to register smart contract addresses and possibly associate an ABI to them.

An **endpoint** may be used as a destination to a **transaction order**, therefore acting as a form of address book entry. Ripple Custody ensures a secure mapping of the **endpoint** to its underlying address when preparing the **transaction** for execution.

An **endpoint** may also be used to validate the destination of a **transaction order** within a policy and to trigger specific approval workflows depending on the attributes of the **endpoint**. For instance, a **policy** may enforce a simplified approval workflow when the destination **endpoint** is marked as whitelisted, or may require an exceptional set of approvers when it is marked as blacklisted.

Lastly, endpoints may also be used to attach meta information to an address. This is the case of smart contract addresses, for instance, which may be attached to the interface, or ABI, of the contract, such that the methods and properties of the contract are known to the system.

The locking of an **endpoint** prevents its use in any context.

### List endpoints

 - [GET /v1/domains/{domainId}/endpoints](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/endpoints/getendpoints.md)

### Get endpoint details

 - [GET /v1/domains/{domainId}/endpoints/{endpointId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/endpoints/getendpoint.md)

## Transactions

A **transaction order** is an order to transfer assets or request an operation on the ledger. In the simplest case, it relates to the transfer of a native cryptocurrency; in more advanced cases, it can apply to the execution of smart contract methods and other on-ledger features.

**Transaction orders** may differ from one ledger protocol to another, but they at least define the account origin, and normally have an amount and a destination address; for some protocols, a single transaction may include multiple destinations and amounts, possibly denominated in various currencies.

**Transaction orders** rely on property `parameters` to define ledger-specific transaction order parameters.

We present below the transaction order parameters for Bitcoin:
 - `outputs`: sequence of pairs of destination and amount;
 - `feeStrategy`: fee calculation strategy, which may be `Low`, `Medium` or `High`; the actual fee amount corresponding to the selected strategy is automatically set by the system at execution time based on a network metrics;
 - `maximumFee`: maximum fee the user is willing to pay to execute the transaction; in rare occasions, Ripple Custody may decide to rebroadcast a transaction with higher fees to ensure inclusion within the ledger, as long as `maximumFee` has not been reached.

For an exhaustive list corresponding to each respective ledger protocol, we refer to the reference manual.

Ripple Custody supports multiple types of destinations for **transaction orders**:
 - ledger address: a ledger address is a protocol-level address, whose format may differ from one ledger protocol to another;
 - account: an account destination is an **account** `id`, which is guaranteed to implicitly resolve to an address of the account; for protocols supporting multiple addresses per account, no guarantee is provided over which account address the resolution leads to;
 - endpoint: an endpoint destination is an **endpoint** `id`, which is guaranteed to implicitly resolve to the address of the endpoint.

Once a **transaction order** is fully approved the order becomes executable. The corresponding **vault** may capture the pending **transaction order** and build and sign a corresponding ledger transaction.

**Transactions** are incoming or outgoing ledger transactions that have been detected on the ledger or shall be broadcast. **Transfers** are the financial representation of their corresponding **transactions**. 

### List transaction orders

 - [GET /v1/domains/{domainId}/transactions/orders](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/transactions/getorders.md)

### Get transaction order details

 - [GET /v1/domains/{domainId}/transactions/orders/{transactionOrderId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/transactions/getorder.md)

### List transfers

 - [GET /v1/domains/{domainId}/transactions/transfers](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/transactions/gettransfers.md)

### Get transfer details

 - [GET /v1/domains/{domainId}/transactions/transfers/{transferId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/transactions/gettransfer.md)

### List transactions

 - [GET /v1/domains/{domainId}/transactions](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/transactions/gettransactions.md)

### Get transaction details

 - [GET /v1/domains/{domainId}/transactions/{transactionId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/transactions/gettransaction.md)

### Dry run a transaction order

 - [POST /v1/domains/{domainId}/transactions/dry-run](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/transactions/dryruntransaction.md)

## Intents

An **intent** represents a signed request to execute an action in Ripple Custody. For the request structure, standard fields, dry-run flow, and example payloads, see [Intent structure](intent-structure.md).

### Propose an intent

 - [POST /v1/intents](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/intents/createintent.md)

### Approve an intent

 - [POST /v1/intents/approve](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/intents/approveintent.md)

### Reject an intent

 - [POST /v1/intents/reject](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/intents/rejectintent.md)

### List intents

 - [GET /v1/domains/{domainId}/intents](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/intents/getintents.md)

### Get intent details

 - [GET /v1/domains/{domainId}/intents/{intentId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/intents/getintent.md)

### Get remaining users

 - [GET /v1/domains/{domainId}/intents/{intentId}/remaining-users](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/intents/getremainingusers.md): This API operation will return the remaining user IDs able to approve for the currently open step of the intent approval process.

### Perform a dry-run for given intent payload

 - [POST /v1/intents/dry-run](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/intents/intentdryrun.md)

## Policies

A **policy** is an operational rule defining the required approval `workflow` for the execution of a particular **intent**. It regulates user entitlements and, if properly configured, ensures that the governance is properly distributed and the system has no single point of compromise. 

In particular, **policies** regulate the approval `workflow` for the creation and update of
- **domains**,
- **users** and their related roles,
- **policies** and their related approval workflows (i.e., creating and updating **policies** is itself subject to a **policy**),
- **accounts**,
- **vaults**,
- **endpoints**,
- **transaction orders.**

**Policies** may also regulate other interactions with the system, such as the release of quarantined, incoming **transfers**.

**Policies** may be refined to cover precise use cases using the property `condition`. A `condition` can be any combination of predicates over the context parameters, which are injected into the evaluation context of the condition at runtime. Such parameters depend on the intent type and other factors. In particular, an **intent** related to a **transaction order** includes information such as the amount, destination(s) address, and source account of the order; an **intent** related to a **user** includes the roles of the user, its alias, etc. For more information about context parameters, we refer to the reference manual.

Because there may be many **policies**, multiple of which may apply to a given **intent**, **policies** are sorted according to property `rank` such that the highest rank policy to match a particular intent is selected.

**Policies** may be defined such as to regulate **intents** within the current domain, or **intents** initiated within a subdomain, or both, with property `scope`. We refer to the reference manual for more information on supervision and governance delegation.

The property `workflow` defines the approval workflow that should be satisfied for an intent to be approved. Each **policy** may have a different approval workflow, which consists in a sequence of steps, each composed of a combination of user roles. For an intent to be executed, all steps of the workflow shall sequentially receive enough approvals (quorum) to evaluate positively. The quorum can't exceed 2000 approvals per step. A single rejection fails the execution of the intent.

The locking of a **policy** ignores it entirely in the process of the policy selection.

### List policies

 - [GET /v1/domains/{domainId}/policies](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/policies/getpolicies.md)

### Get policy details

 - [GET /v1/domains/{domainId}/policies/{policyId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/policies/getpolicy.md)

## Users

A **user** is a human or technical consumer of the Ripple Custody service. 

A user is associated with a public key, which is registered into the system alongside a set of roles. The roles relate to the permissions a user has to access the various entities within the system (as defined within a particular **domain**) as well as to propose, approve and reject the execution of intents (as defined by the approval workflow of a policy).

Users have, in particular, the following properties:
 - `publicKey`: the public key used to authenticate any user request
 - `roles`: a collection of human-readable strings defining the roles of a user

The private key corresponding to `publicKey` is generated on the user-side, either within the mobile approval terminal or programmatically, and is never communicated to the system. We emphasize here that a user key pair is merely used to authenticate the user and approve the execution of **intents**; it is unrelated to the account keys securing the accounts on the ledger. The loss of a **user** key is dealt with by locking the user and creating a new user with a rotated key.

The locking of a **user** prevents its access to the platform entirely.

### List users

 - [GET /v1/domains/{domainId}/users](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/users/getusers.md)

### Get known users roles

 - [GET /v1/domains/{domainId}/users/roles](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/users/getknownuserroles.md)

### Get user details

 - [GET /v1/domains/{domainId}/users/{userId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/users/getuser.md)

### List users belonging to the same public key

 - [GET /v1/me](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/users/getme.md)

## User invitations

**User invitations** are an alternative method to create users. With a user invitation, there is no need for the user to manually share its public key as the process is fully automated in the backend. Moreover it is possible to create invitations that have an expiration date.

### List user invitations

 - [GET /v1/domains/{domainId}/users/invitations](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/user-invitations/paths/~1v1~1domains~1%7Bdomainid%7D~1users~1invitations/get.md): List user invitations

### Create a user invitation

 - [POST /v1/domains/{domainId}/users/invitations](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/user-invitations/paths/~1v1~1domains~1%7Bdomainid%7D~1users~1invitations/post.md): Create a user invitation

### Get user invitation details

 - [GET /v1/domains/{domainId}/users/invitations/{id}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/user-invitations/paths/~1v1~1domains~1%7Bdomainid%7D~1users~1invitations~1%7Bid%7D/get.md): Get user invitation details

### Cancel a user invitation

 - [POST /v1/domains/{domainId}/users/invitations/{id}/cancel](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/user-invitations/paths/~1v1~1domains~1%7Bdomainid%7D~1users~1invitations~1%7Bid%7D~1cancel/post.md): Cancel a user invitation

### Renew a user invitation

 - [POST /v1/domains/{domainId}/users/invitations/{id}/renew](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/user-invitations/paths/~1v1~1domains~1%7Bdomainid%7D~1users~1invitations~1%7Bid%7D~1renew/post.md): Renew a user invitation

### Complete a user invitation

 - [POST /v1/domains/{domainId}/users/invitations/{id}/complete](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/user-invitations/paths/~1v1~1domains~1%7Bdomainid%7D~1users~1invitations~1%7Bid%7D~1complete/post.md): Complete a user invitation

### Fill a user invitation

 - [POST /v1/users/invitations/{idOrCode}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/user-invitations/paths/~1v1~1users~1invitations~1%7Bidorcode%7D/post.md): Fill a user invitation

### Get public data of user invitation

 - [GET /v1/users/invitations/{idOrCode}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/user-invitations/paths/~1v1~1users~1invitations~1%7Bidorcode%7D/get.md): Get public data of user invitation

## Events

An **event** is a notification payload generated through user actions, system signals, and ledger updates.

Events are the notification payloads generated through user actions, system signals, and ledger updates.

Event payloads follow a common pattern including the following fields:
- `id`, a unique identifier for the event,
- `domainId`, a reference to the domain where the event has been issued,
- `sequenceNumber`, a strictly increasing sequence number (but possibly non contiguous),
- `savedAt`, a timestamp, and
- `payload`, additional information depending on the event type.

### List events

 - [GET /v1/domains/{domainId}/events](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/events/getevents.md)

## Requests

A **request** allows to follow the progress of a user request and identify a possible failure. 

Most requests to the system return a `requestId` in the response body, which may be used to inquire on the status of the request.

It is also possible and encouraged to provide a user-defined requestId using the `requestId` HTTP header when submitting intents or when approving/refusing them, this has several advantages:
- If the connection is interrupted between the request and the response the `requestId` will still be known by the caller, which can then check if the request has been submitted to Ripple Custody or not
- If the caller retries to submit another request with an already-used `requestId`, Ripple Custody will prevent this by returning an error, in order to avoid the involuntary replay of a request

**Users** satisfying any of the below conditions are allowed to read a **request** status:
- user is the originator of the request (even if it does not have a read access to `requests`)
- user is in the originator domain and has a role granting him read access to `requests`
- user is in the target domain and has a role granting him read access to `requests`

A **request** will return, in particular, the following fields:
- `lastModifiedAt`, which tracks the last update timestamp of the request;
- `status`, which may be `Processing`, `Succeeded` or `Failed`; a `Failed` status also exposes an additional field detailing the failure reason.
- `history`, which tracks all the intermediate steps of the user request, with details regarding the source component, the status, an eventual hint in case of failure, and a timestamp;

### Get request state

 - [GET /v1/domains/{domainId}/requests/{requestId}](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/requests/getrequeststate.md)

### Get all user requests state

 - [GET /v1/me/requests](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/requests/getalluserrequestsstate.md)

### Get all user requests state in domain

 - [GET /v1/domains/{domainId}/requests](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/requests/getalluserrequestsstateindomain.md)

## SystemProperties

A **SystemProperty** defines a key value secure collection dedicated to store system-wide values.
There are system-defined ones and user-defined ones, access to all is available by properties API. 
User defined one could be created and updated by using SetSystemProperty indent.  

### List system properties

 - [GET /v1/properties](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/systemproperties/getsystemproperties.md)

## External account trading

**External account** refers to account held at exchanges or sub-custodians. The trading API operations allow to obtaining pairs and pricing offered by the exchange.

### Get available trade pairs

 - [GET /v1/domains/{domainId}/external-accounts/providers/{connectionId}/pairs](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-account-trading/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1providers~1%7Bconnectionid%7D~1pairs/get.md): Get available trade pairs

### Get balance directly from a connection and a speci

 - [GET /v1/domains/{domainId}/external-accounts/providers/{connectionId}/balances](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-account-trading/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1providers~1%7Bconnectionid%7D~1balances/get.md): Get balance directly from a connection and a specified ticker name

### Get pair price

 - [GET /v1/domains/{domainId}/external-accounts/providers/{connectionId}/pairs/{baseExternalTickerName}/{quoteExternalTickerName}/price](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-account-trading/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1providers~1%7Bconnectionid%7D~1pairs~1%7Bbaseexternaltickername%7D~1%7Bquoteexternaltickername%7D~1price/get.md): Get pair price

## External account transactions

**External account** refers to account held at exchanges or sub-custodians. The transactions API operations allow to monitoring and listing of orders and transactions that are instructed to the sub-custodian.

### Get external account orders

 - [GET /v1/domains/{domainId}/external-accounts/transactions/orders](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-account-transactions/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1transactions~1orders/get.md): Get external account orders

### Get external account transfers

 - [GET /v1/domains/{domainId}/external-accounts/transactions/transfers](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-account-transactions/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1transactions~1transfers/get.md): Get external account transfers

### Transaction dry run

 - [POST /v1/domains/{domainId}/external-accounts/transactions/dry-run](https://docs.ripple.com/products/custody/v1.15/api/reference/openapi/external-account-transactions/paths/~1v1~1domains~1%7Bdomainid%7D~1external-accounts~1transactions~1dry-run/post.md): Transaction dry run

