diff --git a/content/relayer/integration-tests.mdx b/content/relayer/integration-tests.mdx
new file mode 100644
index 0000000..3cde589
--- /dev/null
+++ b/content/relayer/integration-tests.mdx
@@ -0,0 +1,650 @@
+---
+title: Integration Tests
+---
+
+This guide provides comprehensive information for running and writing integration tests for the OpenZeppelin Relayer. These tests validate multi-network transaction processing, API functionality, and end-to-end system behavior. This documentation serves both end users validating their relayer setup and contributors developing new tests.
+
+## Running Integration Tests
+
+### Prerequisites
+
+Integration tests require specific dependencies and configuration files based on your testing mode.
+
+| Requirement | Description |
+| ------------------------- | ----------------------------------------------------- |
+| Docker and Docker Compose | Required for Docker-based testing (recommended) |
+| Rust 1.88+ | Required for local testing without Docker |
+| Redis instance | Required for local testing without Docker |
+| Test configuration | Mode-specific `config.json` and `registry.json` files |
+
+
+
+Docker-based testing is recommended as it handles all dependencies automatically, including Redis, Anvil, and the Relayer service.
+
+
+
+### Quick Start
+
+#### Local Mode (Anvil) - Recommended
+
+Uses a local Anvil node with no testnet funds required.
+
+```bash
+# 1. One-time setup: Create Anvil keystore
+cast wallet import anvil-test \
+ --private-key PK - from anvil account already funded \
+ --keystore-dir tests/integration/config/local/keys \
+ --unsafe-password "test"
+
+mv tests/integration/config/local/keys/anvil-test \
+ tests/integration/config/local/keys/anvil-test.json
+
+# 2. Copy and configure environment
+cp .env.integration.example .env.integration
+# Edit .env.integration with your API key (any value works for local mode)
+
+# 3. Run tests via Docker
+./scripts/run-integration-docker.sh
+```
+
+The Docker mode uses the `local-anvil-integration` network configuration with the Anvil RPC URL automatically configured.
+
+#### Standalone Mode (Development)
+
+For faster iteration during development with `cargo run` and `cargo test`:
+
+1. Add Anvil relayer to your `config/config.json`. Add this relayer entry to the `relayers` array:
+
+```json
+{
+ "id": "anvil-relayer",
+ "name": "Standalone Anvil Relayer",
+ "network": "localhost",
+ "paused": false,
+ "signer_id": "anvil-signer",
+ "network_type": "evm",
+ "policies": {
+ "min_balance": 0
+ }
+}
+```
+
+2. Add this signer entry to the `signers` array:
+
+```json
+{
+ "id": "anvil-signer",
+ "type": "local",
+ "config": {
+ "path": "tests/integration/config/local/keys/anvil-test.json",
+ "passphrase": {
+ "type": "plain",
+ "value": "test"
+ }
+ }
+}
+```
+
+3. Start Anvil and run tests:
+
+```bash
+# Start Anvil and deploy contracts
+./scripts/anvil-local.sh start
+
+# In another terminal, run relayer
+cargo run
+
+# In another terminal, run tests
+TEST_REGISTRY_PATH=tests/integration/config/local-standalone/registry.json \
+cargo test --features integration-tests --test integration
+
+# When done, stop Anvil
+./scripts/anvil-local.sh stop
+```
+
+
+
+Standalone mode uses the `localhost` network pointing to `http://localhost:8545`, while Docker integration tests use `localhost-integration` pointing to `http://anvil:8545`.
+
+
+
+#### Testnet Mode
+
+For testing against live testnet networks:
+
+
+
+Testnet mode requires real testnet funds. Ensure your test wallet is funded on all networks you plan to test.
+
+
+
+```bash
+# 1. Copy and configure environment
+cp .env.integration.example .env.integration
+# Edit .env.integration with your API key and passphrase
+
+# 2. Copy and configure the testnet config
+cp tests/integration/config/config.example.json tests/integration/config/testnet/config.json
+cp tests/integration/config/registry.example.json tests/integration/config/testnet/registry.json
+# Edit registry.json to enable the networks you want to test
+
+# 3. Run tests via Docker
+MODE=testnet ./scripts/run-integration-docker.sh
+```
+
+### Test Configuration
+
+#### Environment Variables
+
+The `.env.integration` file stores API keys and secrets:
+
+| Variable | Description | Example |
+| --------------------- | ---------------------------------- | -------------------------------------- |
+| `API_KEY` | Relayer API authentication key | `ecaa0daa-f87e-4044-96b8-986638bf92d5` |
+| `KEYSTORE_PASSPHRASE` | Password for local signer keystore | `your-secure-passphrase` |
+| `WEBHOOK_SIGNING_KEY` | Webhook signing key (UUID) | `your-webhook-signing-key-here` |
+| `LOG_LEVEL` | Logging verbosity | `info` |
+
+Create your environment file from the example:
+
+```bash
+cp .env.integration.example .env.integration
+```
+
+#### Registry Configuration
+
+The `registry.json` file stores network-specific test metadata including contract addresses, minimum balances, and network selection. Create mode-specific registry files:
+
+```bash
+# For Local Mode (Anvil with Docker)
+cp tests/integration/config/registry.example.json tests/integration/config/local/registry.json
+
+# For Testnet Mode
+cp tests/integration/config/registry.example.json tests/integration/config/testnet/registry.json
+```
+
+Example registry entry:
+
+```json
+{
+ "networks": {
+ "sepolia": {
+ "network_name": "sepolia",
+ "network_type": "evm",
+ "contracts": {
+ "simple_storage": "0x5379E27d181a94550318d4A44124eCd056678879"
+ },
+ "min_balance": "0.1",
+ "enabled": true
+ }
+ }
+}
+```
+
+Network selection is controlled by the `enabled` flag. Only networks with `"enabled": true` will be included in test runs.
+
+#### Relayer Discovery
+
+Tests automatically discover relayers by querying the running relayer's API (`GET /api/v1/relayers`). This approach:
+
+- Provides a single source of truth by discovering what's actually running
+- Eliminates duplication by removing the need for separate test-specific configuration
+- Works identically in both Docker and standalone modes
+
+The relayer service must be running before tests start. The `config.json` file is only used to start the relayer service, not by the tests themselves.
+
+### Running Specific Tests
+
+#### Via Docker (Recommended)
+
+```bash
+# Run all tests (default MODE=local)
+./scripts/run-integration-docker.sh
+
+# Run tests in testnet mode
+MODE=testnet ./scripts/run-integration-docker.sh
+
+# Build images only
+./scripts/run-integration-docker.sh build
+
+# Stop services
+./scripts/run-integration-docker.sh down
+
+# View logs
+./scripts/run-integration-docker.sh logs
+
+# Open shell in test container
+./scripts/run-integration-docker.sh shell
+
+# Clean up everything
+./scripts/run-integration-docker.sh clean
+```
+
+#### Via Cargo
+
+```bash
+# Run all integration tests
+cargo test --features integration-tests --test integration
+
+# Run specific test
+cargo test --features integration-tests --test integration test_evm_basic_transfer
+
+# Run with verbose output
+RUST_LOG=debug cargo test --features integration-tests --test integration -- --nocapture
+
+# Run with different registry path
+TEST_REGISTRY_PATH=tests/integration/config/testnet/registry.json \
+cargo test --features integration-tests --test integration
+```
+
+## Test Architecture
+
+### Directory Structure
+
+```
+tests/integration/
+├── README.md # Integration testing guide
+├── tests/ # All test files
+│ ├── mod.rs
+│ ├── authorization.rs # API authorization tests
+│ └── evm/ # EVM network tests
+│ ├── mod.rs
+│ ├── basic_transfer.rs # Basic ETH transfer tests
+│ └── contract_interaction.rs
+├── common/ # Shared utilities and helpers
+│ ├── mod.rs
+│ ├── client.rs # RelayerClient for API calls
+│ ├── confirmation.rs # Transaction confirmation helpers
+│ ├── context.rs # Multi-network test runner
+│ ├── evm_helpers.rs # EVM-specific utilities
+│ ├── network_selection.rs # Network filtering
+│ └── registry.rs # Test registry utilities
+├── config/ # Configuration files
+│ ├── config.example.json
+│ ├── registry.example.json
+│ ├── local/ # Local mode configs (gitignored)
+│ ├── local-standalone/ # Standalone mode configs (gitignored)
+│ └── testnet/ # Testnet mode configs (gitignored)
+└── contracts/ # Smart contracts (Foundry)
+ ├── README.md
+ ├── foundry.toml
+ └── src/
+```
+
+The structure separates test files (`tests/`) from shared utilities (`common/`) and configuration (`config/`).
+
+### Test Categories
+
+| Category | Location | Description | Example Tests |
+| --------- | ------------------------------ | ------------------------ | -------------------------------------- |
+| API Tests | `tests/integration/tests/` | REST endpoint validation | Authorization, CRUD operations |
+| EVM Tests | `tests/integration/tests/evm/` | EVM chain operations | Basic transfers, contract interactions |
+
+
+
+Integration tests for Solana and Stellar networks are planned for future releases.
+
+
+
+### Test Registry System
+
+The test registry (`registry.json`) centralizes network-specific test data, eliminating hardcoded values and simplifying network addition.
+
+#### Schema
+
+```json
+{
+ "networks": {
+ "": {
+ "network_name": "string", // Network identifier used by relayer
+ "network_type": "string", // "evm", "solana", or "stellar"
+ "contracts": {
+ "": "address" // Deployed contract addresses
+ },
+ "min_balance": "string", // Minimum balance required (native token)
+ "enabled": true // Whether network is active for testing
+ }
+ }
+}
+```
+
+#### Adding a New Network
+
+1. Add network entry to the appropriate mode-specific `registry.json`:
+
+```json
+{
+ "networks": {
+ "arbitrum-sepolia": {
+ "network_name": "arbitrum-sepolia",
+ "network_type": "evm",
+ "contracts": {
+ "simple_storage": "0x..."
+ },
+ "min_balance": "0.01",
+ "enabled": true
+ }
+ }
+}
+```
+
+2. Add corresponding relayer entry to `config.json` with appropriate signer configuration
+3. Deploy test contracts and update addresses in registry
+4. Fund the signer wallet on the new network
+5. Run tests: `MODE=testnet ./scripts/run-integration-docker.sh`
+
+For detailed network configuration, see the [Network Configuration](/relayer/1.3.x/network_configuration) documentation.
+
+### Test Execution Flow
+
+Integration tests follow a standardized execution flow:
+
+1. **Test Initialization**: Logging is initialized using the `tracing` crate with configurable log levels
+2. **Network Discovery**: Enabled networks are loaded from the mode-specific `registry.json` file
+3. **Relayer Discovery**: Active relayers are discovered via API endpoint `GET /api/v1/relayers`
+4. **Multi-Network Execution**: Tests run across all eligible network and relayer combinations using the `run_multi_network_test` function
+5. **Transaction Confirmation**: Transactions are submitted and confirmed using network-specific timeout configurations via `wait_for_receipt`
+
+The `run_multi_network_test` function in `tests/integration/common/context.rs:57` encapsulates this pattern for consistent test execution across all integration tests.
+
+## Writing New Integration Tests
+
+### Test Structure and Conventions
+
+Integration tests follow standardized naming and structure conventions:
+
+- Test files: `snake_case.rs`
+- Test functions: `test__`
+- All integration tests require the `integration-tests` feature flag
+- Use `#[tokio::test]` for async tests
+
+#### Minimal Test Example
+
+```rust
+use crate::integration::common::{
+ client::RelayerClient,
+ context::run_multi_network_test,
+};
+use openzeppelin_relayer::models::relayer::RelayerResponse;
+
+async fn run_my_test(
+ network: String,
+ relayer_info: RelayerResponse,
+) -> eyre::Result<()> {
+ let client = RelayerClient::from_env()?;
+ // Test logic here
+ Ok(())
+}
+
+#[tokio::test]
+async fn test_my_feature() {
+ run_multi_network_test(
+ "my_feature",
+ is_evm_network,
+ run_my_test
+ ).await;
+}
+```
+
+### Using Test Utilities
+
+The `common/` directory provides essential utilities for integration testing.
+
+#### RelayerClient
+
+The `RelayerClient` in `tests/integration/common/client.rs` provides methods for API interaction:
+
+- `send_transaction(&self, relayer_id: &str, tx_request: Value)` - Submit transactions
+- `get_transaction(&self, relayer_id: &str, tx_id: &str)` - Retrieve transaction status
+- `get_relayer_balance(&self, relayer_id: &str)` - Check relayer balance
+
+Example from `tests/integration/tests/evm/basic_transfer.rs:53`:
+
+```rust
+let client = RelayerClient::from_env()?;
+
+let tx_request = serde_json::json!({
+ "to": "0x000000000000000000000000000000000000dEaD",
+ "value": "1000000000000",
+ "data": "0x",
+ "gas_limit": 21000,
+ "speed": "fast"
+});
+
+let tx_response = client.send_transaction(&relayer.id, tx_request).await?;
+```
+
+#### Multi-Network Runner
+
+The `run_multi_network_test` function in `tests/integration/common/context.rs:57` handles multi-network test execution with network filtering:
+
+```rust
+run_multi_network_test(
+ "test_name",
+ is_evm_network, // Network filter predicate
+ run_test_function // Async test function
+).await;
+```
+
+Available network filters:
+
+- `is_evm_network` - Filters for EVM networks
+- `evm_with_contract("contract_name")` - Filters for EVM networks with specific contract deployed
+
+#### Transaction Confirmation
+
+The `wait_for_receipt` function in `tests/integration/common/confirmation.rs` handles transaction confirmation with network-specific timeouts:
+
+```rust
+use crate::integration::common::confirmation::{wait_for_receipt, ReceiptConfig};
+
+let receipt_config = ReceiptConfig::from_network(&network)?;
+wait_for_receipt(&client, &relayer_id, &tx_id, &receipt_config).await?;
+```
+
+#### Test Registry
+
+Load the test registry to access network configuration and contract addresses:
+
+```rust
+use crate::integration::common::registry::TestRegistry;
+
+let registry = TestRegistry::load()?;
+let network_config = registry.get_network(&network)?;
+let contract_address = registry.get_contract(&network, "simple_storage")?;
+```
+
+### Working with Test Contracts
+
+Test contracts are located in `tests/integration/contracts/` and managed using Foundry.
+
+#### Deploying New Contracts
+
+```bash
+cd tests/integration/contracts
+forge build
+forge create src/YourContract.sol:YourContract \
+ --rpc-url \
+ --private-key
+```
+
+After deployment, add the contract address to the appropriate `registry.json` file:
+
+```json
+{
+ "networks": {
+ "sepolia": {
+ "contracts": {
+ "your_contract": "0x..."
+ }
+ }
+ }
+}
+```
+
+### Best Practices
+
+When writing integration tests, follow these guidelines:
+
+- **Use structured logging**: Leverage the `tracing` crate for informative, filterable logs with `info!`, `debug!`, and `error!` macros
+- **Test isolation**: Each test should be independent and not rely on state from other tests
+- **Error handling**: Use `eyre::Result` for clear error propagation and context
+- **Timeouts**: Configure appropriate timeouts based on network characteristics using `ReceiptConfig`
+
+Example structured logging from `tests/integration/tests/evm/basic_transfer.rs:25`:
+
+```rust
+use tracing::{info, debug, info_span};
+
+async fn run_basic_transfer_test(
+ network: String,
+ relayer_info: RelayerResponse,
+) -> eyre::Result<()> {
+ let _span = info_span!("basic_transfer",
+ network = %network,
+ relayer = %relayer_info.id
+ ).entered();
+
+ info!("Starting basic transfer test");
+ debug!(relayer = ?relayer_info, "Full relayer details");
+
+ // Test implementation
+
+ info!("Test completed successfully");
+ Ok(())
+}
+```
+
+## Troubleshooting
+
+### Common Issues
+
+#### MacMismatch Error
+
+
+
+The keystore passphrase doesn't match the password used to create the keystore.
+
+
+
+**Error message:**
+
+```
+Error: MacMismatch
+```
+
+**Solution:** Ensure `KEYSTORE_PASSPHRASE` in `.env.integration` matches the password used when creating the keystore file.
+
+#### Connection Refused
+
+
+
+Cannot connect to required services (Redis, Relayer, or Anvil).
+
+
+
+**Error message:**
+
+```
+Error: Connection refused (os error 111)
+```
+
+**Solution:** Ensure all required services are running. For Docker mode:
+
+```bash
+docker-compose -f docker-compose.integration.yml ps
+```
+
+For standalone mode, verify Redis and the Relayer service are running.
+
+#### Insufficient Funds
+
+
+
+Test wallet does not have sufficient funds for transactions.
+
+
+
+**Error message:**
+
+```
+Error: insufficient funds for transfer
+```
+
+**Solution:** Fund the test wallet. Check the relayer logs for the signer address:
+
+```bash
+docker-compose -f docker-compose.integration.yml logs relayer | grep address
+```
+
+Then use a testnet faucet to fund the address.
+
+#### Network Timeout
+
+
+
+Transaction confirmation timeout exceeded.
+
+
+
+**Error message:**
+
+```
+Error: Transaction confirmation timeout
+```
+
+**Solution:**
+
+- Verify the network RPC endpoint is accessible
+- Check if the network is experiencing congestion
+- Review network-specific timeout configurations in `ReceiptConfig`
+
+### Debugging Techniques
+
+#### View Container Logs
+
+```bash
+# All services
+./scripts/run-integration-docker.sh logs
+
+# Specific service
+docker-compose -f docker-compose.integration.yml logs integration-relayer
+docker-compose -f docker-compose.integration.yml logs integration-tests
+```
+
+#### Interactive Shell Access
+
+Access the test container for debugging:
+
+```bash
+./scripts/run-integration-docker.sh shell
+```
+
+#### Run Single Test with Verbose Output
+
+```bash
+RUST_LOG=debug \
+ cargo test --features integration-tests --test integration test_name -- --nocapture
+```
+
+The `--nocapture` flag shows real-time log output during test execution.
+
+### Cleanup and Maintenance
+
+Remove all Docker resources if tests leave behind resources:
+
+```bash
+# Using helper script
+./scripts/run-integration-docker.sh clean
+
+# Or manually
+docker-compose -f docker-compose.integration.yml down -v --remove-orphans
+```
+
+## Additional Resources
+
+- [Quick Start Guide](/relayer/1.3.x/quickstart) - Initial setup and configuration
+- [Project Structure](/relayer/1.3.x/structure) - Overview of project organization
+- [API Reference](/relayer/1.3.x/api) - Detailed API documentation
+- [Network Configuration](/relayer/1.3.x/network_configuration) - Network setup guide
+- [GitHub Repository](https://github.com/OpenZeppelin/openzeppelin-relayer) - Source code and examples
diff --git a/src/navigation/ethereum-evm.json b/src/navigation/ethereum-evm.json
index 0706318..165be36 100644
--- a/src/navigation/ethereum-evm.json
+++ b/src/navigation/ethereum-evm.json
@@ -1079,6 +1079,11 @@
},
"children": []
},
+ {
+ "type": "page",
+ "name": "Integration Tests",
+ "url": "/relayer/integration-tests"
+ },
{
"type": "page",
"name": "Changelog",