> ## Documentation Index
> Fetch the complete documentation index at: https://docs.peaq.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# ROS 2 service catalog

> Canonical peaqOS ROS 2 machine endpoints plus documented agent aliases, grouped by SDK capability.

This page lists the canonical machine endpoints and documented agent aliases exposed under `/peaqos_node`. Requests use ROS 2 service types from `peaq_ros2_interfaces`. All examples assume the node is running with a populated `peaq_robot.yaml`; see [ROS 2 configuration](/peaqos/sdk-reference/ros2/configuration).

<Tip>
  Quote EVM addresses and large integers in `ros2 service call` YAML payloads. Unquoted addresses can parse as numbers and break the request.
</Tip>

## Wallets

Local EVM wallet registry. Service calls return public metadata only: `address`, `account_id`, `chain_id`, `network`, `label`, and `created_at`. Private keys never cross ROS.

| Service                      | Type                                          |
| :--------------------------- | :-------------------------------------------- |
| `/peaqos_node/wallet/create` | `peaq_ros2_interfaces/srv/PeaqosCreateWallet` |
| `/peaqos_node/wallet/list`   | `peaq_ros2_interfaces/srv/PeaqosListWallets`  |
| `/peaqos_node/wallet/get`    | `peaq_ros2_interfaces/srv/PeaqosGetWallet`    |
| `/peaqos_node/wallet/delete` | `peaq_ros2_interfaces/srv/PeaqosDeleteWallet` |

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
# Create
ros2 service call /peaqos_node/wallet/create \
  peaq_ros2_interfaces/srv/PeaqosCreateWallet \
  "{label: 'robot-001'}"

# List
ros2 service call /peaqos_node/wallet/list \
  peaq_ros2_interfaces/srv/PeaqosListWallets "{}"

# Get
ros2 service call /peaqos_node/wallet/get \
  peaq_ros2_interfaces/srv/PeaqosGetWallet \
  "{address: '<MACHINE_EVM_ADDRESS>'}"

# Delete
ros2 service call /peaqos_node/wallet/delete \
  peaq_ros2_interfaces/srv/PeaqosDeleteWallet \
  "{address: '<MACHINE_EVM_ADDRESS>'}"
```

SDK import, export, and `from_wallet` flows are intentionally **not** exposed over ROS because they require private keys, mnemonics, or passphrases. Use the [Python SDK](/peaqos/sdk-reference/sdk-python) or [CLI](/peaqos/cli) for those.

## Gas Station

Gas Station onboarding for fresh machine wallets. 2FA codes are request-only and should not be logged.

| Service                           | Type                                              |
| :-------------------------------- | :------------------------------------------------ |
| `/peaqos_node/faucet/setup_2fa`   | `peaq_ros2_interfaces/srv/PeaqosSetupFaucet2FA`   |
| `/peaqos_node/faucet/confirm_2fa` | `peaq_ros2_interfaces/srv/PeaqosConfirmFaucet2FA` |
| `/peaqos_node/wallet/fund`        | `peaq_ros2_interfaces/srv/PeaqosFundWallet`       |

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
# 1. Start 2FA enrollment for the owner
ros2 service call /peaqos_node/faucet/setup_2fa \
  peaq_ros2_interfaces/srv/PeaqosSetupFaucet2FA \
  "{owner_address: '<OWNER_EVM_ADDRESS>', qr_format: 'svg'}"

# 2. Confirm with the OTP from the authenticator
ros2 service call /peaqos_node/faucet/confirm_2fa \
  peaq_ros2_interfaces/srv/PeaqosConfirmFaucet2FA \
  "{owner_address: '<OWNER_EVM_ADDRESS>', two_factor_code: '123456'}"

# 3. Fund the target wallet through the Gas Station
ros2 service call /peaqos_node/wallet/fund \
  peaq_ros2_interfaces/srv/PeaqosFundWallet \
  "{owner_address: '<OWNER_EVM_ADDRESS>', target_address: '<MACHINE_EVM_ADDRESS>', chain_id: '3338', two_factor_code: '123456', request_id: ''}"
```

See the [error reference](/peaqos/sdk-reference/errors) for `INVALID_2FA`, `2FA_LOCKED`, `RATE_LIMITED`, and `CAP_EXCEEDED_OWNER`.

## Registration

| Service                             | Type                                             |
| :---------------------------------- | :----------------------------------------------- |
| `/peaqos_node/machine/register`     | `peaq_ros2_interfaces/srv/PeaqosRegisterMachine` |
| `/peaqos_node/agent/register`       | `peaq_ros2_interfaces/srv/PeaqosRegisterAgent`   |
| `/peaqos_node/machine/register_for` | `peaq_ros2_interfaces/srv/PeaqosRegisterFor`     |
| `/peaqos_node/agent/register_for`   | `peaq_ros2_interfaces/srv/PeaqosRegisterFor`     |

`/machine/register` and `/agent/register` are interchangeable surfaces over the same registration call. Pick whichever language matches your fleet model. `/machine/register_for` and `/agent/register_for` are likewise the same handler under two paths.

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
# Self-managed: machine signs for itself
ros2 service call /peaqos_node/machine/register \
  peaq_ros2_interfaces/srv/PeaqosRegisterMachine \
  "{address: '<MACHINE_EVM_ADDRESS>'}"

# Equivalent agent-flavored alias
ros2 service call /peaqos_node/agent/register \
  peaq_ros2_interfaces/srv/PeaqosRegisterAgent \
  "{address: '<AGENT_EVM_ADDRESS>'}"

# Proxy operator: operator signs on behalf of a fleet machine
ros2 service call /peaqos_node/machine/register_for \
  peaq_ros2_interfaces/srv/PeaqosRegisterFor \
  "{proxy_address: '<OPERATOR_EVM_ADDRESS>', machine_address: '<MACHINE_EVM_ADDRESS>'}"
```

For background on the two patterns, see [Self-managed onboarding](/peaqos/guides/self-managed-onboarding) and [Proxy operator fleet](/peaqos/guides/proxy-operator-fleet).

## Machine NFT

| Service                        | Type                                       |
| :----------------------------- | :----------------------------------------- |
| `/peaqos_node/nft/mint`        | `peaq_ros2_interfaces/srv/PeaqosMintNft`   |
| `/peaqos_node/nft/token_id_of` | `peaq_ros2_interfaces/srv/PeaqosTokenIdOf` |

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
ros2 service call /peaqos_node/nft/mint \
  peaq_ros2_interfaces/srv/PeaqosMintNft \
  "{signer_address: '<OWNER_OR_PROXY_ADDRESS>', machine_id: 1, recipient: '<RECIPIENT_EVM_ADDRESS>'}"

ros2 service call /peaqos_node/nft/token_id_of \
  peaq_ros2_interfaces/srv/PeaqosTokenIdOf \
  "{signer_address: '<SIGNER_EVM_ADDRESS>', machine_id: 1}"
```

## DID attributes

| Service                                     | Type                                                       |
| :------------------------------------------ | :--------------------------------------------------------- |
| `/peaqos_node/did/read_attribute`           | `peaq_ros2_interfaces/srv/PeaqosReadDidAttribute`          |
| `/peaqos_node/did/write_machine_attributes` | `peaq_ros2_interfaces/srv/PeaqosWriteMachineDidAttributes` |
| `/peaqos_node/did/write_proxy_attributes`   | `peaq_ros2_interfaces/srv/PeaqosWriteProxyDidAttributes`   |

`/did/write_machine_attributes` is the standard machine DID write path the MCR API consumes. It writes `machineId`, `nftTokenId`, `operatorDid`, `documentationUrl`, `dataApi`, and `dataVisibility` in one call. `/did/write_proxy_attributes` is the proxy/operator equivalent; it atomically writes the two standard proxy DID attributes (`proxy_agent_id` and the list of `machine_ids` the operator manages).

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
# Read one attribute by name from the DID precompile
ros2 service call /peaqos_node/did/read_attribute \
  peaq_ros2_interfaces/srv/PeaqosReadDidAttribute \
  "{signer_address: '<SIGNER_EVM_ADDRESS>', did_address: '<DID_EVM_ADDRESS>', name: 'machineId'}"

# Write the standard machine attributes in one shot
ros2 service call /peaqos_node/did/write_machine_attributes \
  peaq_ros2_interfaces/srv/PeaqosWriteMachineDidAttributes \
  "{signer_address: '<MACHINE_EVM_ADDRESS>', machine_id: 1, nft_token_id: 1, operator_did: 'did:peaq:<OPERATOR_EVM_ADDRESS>', documentation_url: 'https://docs.example/robot-001', data_api: 'https://api.example/robot-001', data_visibility: 'onchain'}"

# Write proxy/operator DID attributes
ros2 service call /peaqos_node/did/write_proxy_attributes \
  peaq_ros2_interfaces/srv/PeaqosWriteProxyDidAttributes \
  "{signer_address: '<PROXY_EVM_ADDRESS>', proxy_agent_id: 1, machine_ids: [1, 2, 3]}"
```

## Events

| Service                            | Type                                               |
| :--------------------------------- | :------------------------------------------------- |
| `/peaqos_node/events/validate`     | `peaq_ros2_interfaces/srv/PeaqosValidateEvent`     |
| `/peaqos_node/events/submit`       | `peaq_ros2_interfaces/srv/PeaqosSubmitEvent`       |
| `/peaqos_node/events/batch_submit` | `peaq_ros2_interfaces/srv/PeaqosBatchSubmitEvents` |

`/events/validate` runs locally: it computes the data hash and checks the payload before you spend gas. `/events/batch_submit` goes through the peaq batch precompile (`0x...0805`) so a multi-event submission is atomic on chain.

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
# Validate locally
ros2 service call /peaqos_node/events/validate \
  peaq_ros2_interfaces/srv/PeaqosValidateEvent \
  "{machine_id: 1, event_type: 1, value: 1, timestamp: 1770000000, raw_data_hex: '0x', trust_level: 1, source_chain_id: 3338, source_tx_hash: '', metadata_hex: '0x7b7d'}"

# Submit one event
ros2 service call /peaqos_node/events/submit \
  peaq_ros2_interfaces/srv/PeaqosSubmitEvent \
  "{signer_address: '<MACHINE_EVM_ADDRESS>', machine_id: 1, event_type: 1, value: 1, timestamp: 1770000000, raw_data_hex: '0x', trust_level: 1, source_chain_id: 3338, source_tx_hash: '', metadata_hex: '0x7b7d'}"

# Atomic batch
ros2 service call /peaqos_node/events/batch_submit \
  peaq_ros2_interfaces/srv/PeaqosBatchSubmitEvents \
  "{signer_address: '<MACHINE_EVM_ADDRESS>', events_json: '[{\"machine_id\":1,\"event_type\":1,\"value\":1,\"timestamp\":1770000000,\"raw_data_hex\":\"0x\",\"trust_level\":1,\"source_chain_id\":3338,\"source_tx_hash\":\"\",\"metadata_hex\":\"0x7b7d\"}]'}"
```

For event field rules, see [Events](/peaqos/concepts/events) and [SDK JS event validation](/peaqos/sdk-reference/sdk-js#validatesubmiteventparams).

## MCR queries

Hosted MCR API queries. Returned bodies are SDK JSON passthrough; operator-fleet results may include per-machine `negative_flag` and top-level `pagination`.

| Service                              | Type                                                   |
| :----------------------------------- | :----------------------------------------------------- |
| `/peaqos_node/mcr/query`             | `peaq_ros2_interfaces/srv/PeaqosQueryMcr`              |
| `/peaqos_node/mcr/machine`           | `peaq_ros2_interfaces/srv/PeaqosQueryMachine`          |
| `/peaqos_node/mcr/operator_machines` | `peaq_ros2_interfaces/srv/PeaqosQueryOperatorMachines` |

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
ros2 service call /peaqos_node/mcr/query \
  peaq_ros2_interfaces/srv/PeaqosQueryMcr \
  "{did: 'did:peaq:<MACHINE_EVM_ADDRESS>'}"

ros2 service call /peaqos_node/mcr/machine \
  peaq_ros2_interfaces/srv/PeaqosQueryMachine \
  "{did: 'did:peaq:<MACHINE_EVM_ADDRESS>'}"

ros2 service call /peaqos_node/mcr/operator_machines \
  peaq_ros2_interfaces/srv/PeaqosQueryOperatorMachines \
  "{did: 'did:peaq:<OPERATOR_EVM_ADDRESS>'}"
```

The full HTTP API is documented under [API Reference](/peaqos/api-reference/overview).

## Smart accounts

ERC-4337 machine accounts are deployed through `MachineAccountFactory`. Address prediction is deterministic (CREATE2 salt) and cheap; call `address` first, deploy second.

| Service                              | Type                                                    |
| :----------------------------------- | :------------------------------------------------------ |
| `/peaqos_node/smart_account/address` | `peaq_ros2_interfaces/srv/PeaqosGetSmartAccountAddress` |
| `/peaqos_node/smart_account/deploy`  | `peaq_ros2_interfaces/srv/PeaqosDeploySmartAccount`     |

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
# Predict address (no tx)
ros2 service call /peaqos_node/smart_account/address \
  peaq_ros2_interfaces/srv/PeaqosGetSmartAccountAddress \
  "{signer_address: '<SIGNER_EVM_ADDRESS>', owner: '<OWNER_EVM_ADDRESS>', machine: '<MACHINE_EVM_ADDRESS>', daily_limit: '', salt: '0'}"

# Deploy
ros2 service call /peaqos_node/smart_account/deploy \
  peaq_ros2_interfaces/srv/PeaqosDeploySmartAccount \
  "{signer_address: '<SIGNER_EVM_ADDRESS>', owner: '<OWNER_EVM_ADDRESS>', machine: '<MACHINE_EVM_ADDRESS>', daily_limit: '', salt: '0'}"
```

`daily_limit` is kept on the service for backward compatibility. The current `MachineAccountFactory` ignores it, so an empty string is fine. Both calls require `peaq_os.contracts.machine_account_factory` (or `MACHINE_ACCOUNT_FACTORY_ADDRESS`) to be set.

## Bridge

| Service                            | Type                                                  |
| :--------------------------------- | :---------------------------------------------------- |
| `/peaqos_node/bridge/nft`          | `peaq_ros2_interfaces/srv/PeaqosBridgeNft`            |
| `/peaqos_node/bridge/wait_arrival` | `peaq_ros2_interfaces/srv/PeaqosWaitForBridgeArrival` |

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
ros2 service call /peaqos_node/bridge/nft \
  peaq_ros2_interfaces/srv/PeaqosBridgeNft \
  "{signer_address: '<OWNER_EVM_ADDRESS>', token_id: 1, source: 'peaq', destination: 'base', recipient: '<RECIPIENT_EVM_ADDRESS>', base_rpc_url: '', base_nft_address: '', options_hex: ''}"

ros2 service call /peaqos_node/bridge/wait_arrival \
  peaq_ros2_interfaces/srv/PeaqosWaitForBridgeArrival \
  "{dst_rpc_url: 'https://mainnet.base.org', dst_nft_address: '0xee8A521eA434b11F956E2402beC5eBfa753Babfa', token_id: 1, timeout: 900}"
```

Bridging has its own page: see [Bridge](/peaqos/sdk-reference/ros2/bridge) for the full peaq to Base flow, gas requirements, and arrival polling.

<Warning>
  Reverse Base to peaq bridging requires Base ETH on the signer wallet.
</Warning>

## Tips

* Source ROS and the workspace before every session: `source /opt/ros/<distro>/setup.bash && source install/setup.bash`.
* Stream logs in another terminal: `tail -f /tmp/peaqos_node.log`.
* For batched onboarding flows, prefer `/events/batch_submit` over multiple `/events/submit` calls: single tx, lower fees.
