{
  "openapi": "3.1.0",
  "info": {
    "title": "MultiHopper API",
    "version": "1.0.0",
    "description": "Permissionless, non-custodial programmable routing infrastructure for AI agents and developers moving digital assets onchain. Configurable timing entropy, programmable hop count control, composable routing parameters, and regulatory-ready onchain abstraction on Solana.\n\nThis is a public partial specification. Full endpoint documentation, request/response schemas, and SDK references are provided to whitelisted partners. Register at https://www.multihopper.com/developers.\n\n## Machine Discovery\n\nAll three machine-readable discovery surfaces are live and documented at:\nhttps://www.multihopper.com/developers#machine-discovery\n\n- **OpenAPI spec** (this file): https://www.multihopper.com/openapi.json\n- **MCP server card** (SEP-1649): https://www.multihopper.com/.well-known/mcp/server-card.json\n- **LLM discovery file**: https://www.multihopper.com/llms.txt",
    "contact": {
      "name": "MultiHopper Developer Relations",
      "url": "https://www.multihopper.com/developers",
      "x-twitter": "https://x.com/multihopper"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://www.multihopper.com"
    },
    "x-logo": {
      "url": "https://www.multihopper.com/logo.png",
      "altText": "MultiHopper"
    },
    "x-llms-txt": "https://www.multihopper.com/llms.txt",
    "x-mcp-server-card": "https://www.multihopper.com/.well-known/mcp/server-card.json"
  },
  "externalDocs": {
    "description": "MultiHopper Developer Whitelist & Machine Discovery — register for full API access, or browse all agent discovery surfaces",
    "url": "https://www.multihopper.com/developers#machine-discovery"
  },
  "servers": [
    {
      "url": "https://api.multihopper.com/v1",
      "description": "Production (requires API key — whitelist access only)"
    },
    {
      "url": "https://sandbox.multihopper.com/v1",
      "description": "Sandbox (requires API key — issued with whitelist approval)"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Routes",
      "description": "Initiate, estimate, and query programmable multi-hop onchain transfers"
    },
    {
      "name": "Wallets",
      "description": "Query the active routing wallet pool"
    },
    {
      "name": "Health",
      "description": "API health and status"
    }
  ],
  "paths": {
    "/route": {
      "post": {
        "operationId": "initiateRoute",
        "summary": "Initiate a programmable multi-hop transfer",
        "description": "Initiate a non-custodial, compliance-checked multi-hop transfer on Solana. Specify source, destination, amount, timing window (min/max seconds), and hop count (exact or min/max range). MultiHopper randomises delivery within the timing window and executes the route across the active wallet pool. Compliance checks run on every wallet in the route.",
        "tags": ["Routes"],
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RouteRequest"
              },
              "examples": {
                "basic_sol_transfer": {
                  "summary": "Basic SOL transfer with timing window",
                  "value": {
                    "source_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
                    "destination_address": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
                    "amount": 1000000000,
                    "timing_window_min": 300,
                    "timing_window_max": 900,
                    "hop_count_min": 3,
                    "hop_count_max": 7,
                    "webhook_url": "https://your-app.com/webhooks/multihopper"
                  }
                },
                "fixed_hop_spl_transfer": {
                  "summary": "Fixed hop count SPL token transfer",
                  "value": {
                    "source_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
                    "destination_address": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
                    "amount": 1000000,
                    "token_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                    "timing_window_min": 60,
                    "timing_window_max": 300,
                    "hop_count": 5
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Route accepted and queued for execution",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RouteResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "403": {
            "description": "API key not whitelisted or insufficient permissions",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "422": {
            "description": "Compliance check failed — source or destination address flagged",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ComplianceErrorResponse" }
              }
            }
          }
        }
      }
    },
    "/route/estimate": {
      "post": {
        "operationId": "estimateRoute",
        "summary": "Estimate fees and timing for a route",
        "description": "Preview estimated fees, timing range, and hop details for a route before committing funds. No funds are moved. Compliance pre-checks run on source and destination addresses.",
        "tags": ["Routes"],
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RouteEstimateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Route estimate returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RouteEstimateResponse"
                }
              }
            }
          },
          "400": { "description": "Invalid request parameters" },
          "401": { "description": "Missing or invalid API key" },
          "422": { "description": "Compliance pre-check failed" }
        }
      }
    },
    "/route/{id}": {
      "get": {
        "operationId": "getRoute",
        "summary": "Get transfer status by route ID",
        "description": "Retrieve the current status, hop details, timing, and compliance information for a transfer by its route ID.",
        "tags": ["Routes"],
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Route ID returned by POST /route",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "Route details returned",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/RouteDetail" }
              }
            }
          },
          "401": { "description": "Missing or invalid API key" },
          "404": { "description": "Route ID not found" }
        }
      }
    },
    "/route/{id}/hops": {
      "get": {
        "operationId": "getRouteHops",
        "summary": "Get individual hop details for a transfer",
        "description": "Returns the full hop-by-hop breakdown of a transfer, including each transit wallet address, timing at each hop, and compliance status per hop.",
        "tags": ["Routes"],
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Route ID",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "Hop details returned",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/RouteHopsResponse" }
              }
            }
          },
          "401": { "description": "Missing or invalid API key" },
          "404": { "description": "Route ID not found" }
        }
      }
    },
    "/wallets/pool": {
      "get": {
        "operationId": "getWalletPool",
        "summary": "Query the active routing wallet pool",
        "description": "Returns metadata about the active routing wallet pool — the 500 busiest Solana wallets, smart contracts, and cold storage addresses used as transit hops. Includes pool size, last updated timestamp, and compliance coverage statistics.",
        "tags": ["Wallets"],
        "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": {
            "description": "Wallet pool metadata returned",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/WalletPoolResponse" }
              }
            }
          },
          "401": { "description": "Missing or invalid API key" }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "API health check",
        "description": "Returns API health status. No authentication required.",
        "tags": ["Health"],
        "security": [],
        "responses": {
          "200": {
            "description": "API is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string", "example": "ok" },
                    "version": { "type": "string", "example": "1.0.0" },
                    "network": { "type": "string", "example": "mainnet-beta" },
                    "timestamp": { "type": "string", "format": "date-time" }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key issued upon whitelist approval. Register at https://www.multihopper.com/developers"
      }
    },
    "schemas": {
      "RouteRequest": {
        "type": "object",
        "required": ["source_address", "destination_address", "amount"],
        "properties": {
          "source_address": {
            "type": "string",
            "description": "Solana wallet address of the sender (base58)",
            "example": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
          },
          "destination_address": {
            "type": "string",
            "description": "Solana wallet address of the recipient (base58)",
            "example": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"
          },
          "amount": {
            "type": "integer",
            "description": "Amount in lamports (SOL) or token base units",
            "example": 1000000000
          },
          "token_mint": {
            "type": "string",
            "description": "SPL token mint address (omit for native SOL)",
            "example": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
          },
          "timing_window_min": {
            "type": "integer",
            "description": "Minimum delivery time in seconds. MultiHopper randomises actual delivery within [min, max].",
            "example": 300,
            "minimum": 0
          },
          "timing_window_max": {
            "type": "integer",
            "description": "Maximum delivery time in seconds.",
            "example": 900,
            "minimum": 1
          },
          "hop_count": {
            "type": "integer",
            "description": "Exact hop count. Use instead of hop_count_min/max for fixed routing.",
            "example": 5,
            "minimum": 1,
            "maximum": 20
          },
          "hop_count_min": {
            "type": "integer",
            "description": "Minimum hop count for randomised range.",
            "example": 3,
            "minimum": 1
          },
          "hop_count_max": {
            "type": "integer",
            "description": "Maximum hop count for randomised range.",
            "example": 7,
            "minimum": 1,
            "maximum": 20
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "Optional URL to receive lifecycle webhook events (transfer.initiated, transfer.completed, transfer.failed, compliance.flagged)",
            "example": "https://your-app.com/webhooks/multihopper"
          }
        }
      },
      "RouteResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique route ID — use to query status",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "status": {
            "type": "string",
            "enum": ["initiated", "in_progress", "completed", "failed"],
            "example": "initiated"
          },
          "estimated_delivery_min": {
            "type": "integer",
            "description": "Estimated minimum delivery time in seconds",
            "example": 300
          },
          "estimated_delivery_max": {
            "type": "integer",
            "description": "Estimated maximum delivery time in seconds",
            "example": 900
          },
          "hop_count": {
            "type": "integer",
            "description": "Actual hop count selected by MultiHopper within the requested range",
            "example": 5
          },
          "estimated_fee_lamports": {
            "type": "integer",
            "description": "Estimated total fee in lamports",
            "example": 5000
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RouteEstimateRequest": {
        "type": "object",
        "required": ["source_address", "destination_address", "amount"],
        "properties": {
          "source_address": { "type": "string" },
          "destination_address": { "type": "string" },
          "amount": { "type": "integer" },
          "token_mint": { "type": "string" },
          "timing_window_min": { "type": "integer" },
          "timing_window_max": { "type": "integer" },
          "hop_count_min": { "type": "integer" },
          "hop_count_max": { "type": "integer" }
        }
      },
      "RouteEstimateResponse": {
        "type": "object",
        "properties": {
          "estimated_fee_lamports": { "type": "integer", "example": 5000 },
          "estimated_fee_usd": { "type": "number", "example": 0.0008 },
          "estimated_delivery_min": { "type": "integer", "example": 300 },
          "estimated_delivery_max": { "type": "integer", "example": 900 },
          "hop_count_range": {
            "type": "object",
            "properties": {
              "min": { "type": "integer", "example": 3 },
              "max": { "type": "integer", "example": 7 }
            }
          },
          "compliance_pre_check": {
            "type": "object",
            "properties": {
              "source_clear": { "type": "boolean", "example": true },
              "destination_clear": { "type": "boolean", "example": true }
            }
          },
          "excess_gas_refund_eligible": { "type": "boolean", "example": true }
        }
      },
      "RouteDetail": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "status": {
            "type": "string",
            "enum": ["initiated", "in_progress", "completed", "failed", "compliance_flagged"]
          },
          "source_address": { "type": "string" },
          "destination_address": { "type": "string" },
          "amount": { "type": "integer" },
          "token_mint": { "type": "string", "nullable": true },
          "hop_count": { "type": "integer" },
          "timing_window_min": { "type": "integer" },
          "timing_window_max": { "type": "integer" },
          "actual_delivery_seconds": { "type": "integer", "nullable": true },
          "fee_lamports": { "type": "integer" },
          "excess_gas_refund_lamports": { "type": "integer" },
          "created_at": { "type": "string", "format": "date-time" },
          "completed_at": { "type": "string", "format": "date-time", "nullable": true },
          "compliance": {
            "type": "object",
            "properties": {
              "all_clear": { "type": "boolean" },
              "flagged_hops": { "type": "array", "items": { "type": "integer" } }
            }
          }
        }
      },
      "RouteHopsResponse": {
        "type": "object",
        "properties": {
          "route_id": { "type": "string", "format": "uuid" },
          "hops": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "hop_index": { "type": "integer", "example": 1 },
                "wallet_address": { "type": "string" },
                "arrived_at": { "type": "string", "format": "date-time", "nullable": true },
                "departed_at": { "type": "string", "format": "date-time", "nullable": true },
                "compliance_clear": { "type": "boolean" },
                "tx_signature": { "type": "string", "nullable": true }
              }
            }
          }
        }
      },
      "WalletPoolResponse": {
        "type": "object",
        "properties": {
          "pool_size": { "type": "integer", "example": 500 },
          "last_updated": { "type": "string", "format": "date-time" },
          "compliance_coverage": {
            "type": "object",
            "properties": {
              "wallets_checked": { "type": "integer", "example": 500 },
              "wallets_clear": { "type": "integer", "example": 500 },
              "last_scan": { "type": "string", "format": "date-time" }
            }
          },
          "network": { "type": "string", "example": "mainnet-beta" }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" },
          "code": { "type": "string" }
        }
      },
      "ComplianceErrorResponse": {
        "type": "object",
        "properties": {
          "error": { "type": "string", "example": "compliance_check_failed" },
          "message": { "type": "string" },
          "flagged_address": { "type": "string" },
          "flag_reason": { "type": "string" }
        }
      }
    }
  },
  "x-mcp-discovery": {
    "server_card": "https://www.multihopper.com/.well-known/mcp/server-card.json",
    "llms_txt": "https://www.multihopper.com/llms.txt",
    "human_discovery_page": "https://www.multihopper.com/developers#machine-discovery",
    "compatible_frameworks": [
      "Claude Desktop",
      "Cursor",
      "VS Code",
      "LangChain",
      "CrewAI",
      "AutoGen",
      "OpenAI Agents SDK"
    ],
    "mcp_tool_generation": "This OpenAPI spec is compatible with mcp-openapi for automatic MCP tool definition generation. All three discovery surfaces are documented at https://www.multihopper.com/developers#machine-discovery"
  }
}
