Skip to content
Minotaur
+ 05 · API Reference

API · Apps

App catalog endpoints: register, validate, deploy, manifest, status, score, and per-app scoring updates.

All endpoints below are mounted under /v1 on the validator API (https://api.minotaursubnet.com). The CORS allowlist covers https://app.minotaursubnet.com.

GET /v1/apps/

List all App Intents, optionally filtered by deployer address or status.

Query parameters

  • deployerstr
  • statusstr

POST /v1/apps/

Create a new App Intent with developer-provided JS and Solidity code.

Request body

  • bodyCreateAppRequest (required) (model CreateAppRequest)
    • name: str = Field(..., description='Human-readable name')
    • description: str = Field('', description='What this app does')
    • supported_chains: list[int] = Field(..., description='Chain IDs (e.g. [1, 8453])')
    • js_code: str = Field(..., description='JS scoring code (required)')
    • solidity_code: str = Field(..., description='Solidity contract code (required)')
    • constructor_args: list[list[str]] | None = Field(None, description='Extra constructor args: [[abi_type, value], ...]')
    • deployer: str = Field('', description='Deployer/owner address (only this address can edit the app). Claimed unless owner_signature proves it.')
    • fee_mode: str = Field('', description="Per-App on-chain fee mode: 'USER' (users pay) or 'APP' (the App's paymaster pays). Empty = operator default (FEE_MODE_DEFAULT).")
    • contract_version: str = Field('', description="Contract base generation: 'v1' (AppIntentBase) or 'v2' (AppIntentBaseV2). Empty = v1.")
    • owner_signature: str = Field('', description="EIP-712 'create_app' signature over the app content (keccak256(js.trim()+'\\u241f'+solidity.trim())). When present, the owner is the RECOVERED signer (proven, not claimed).")
    • owner_deadline: int = Field(0, description='Unix-seconds expiry the owner_signature was signed with.')

GET /v1/apps/manifests

Return manifests for all apps (bulk discovery for miners).

POST /v1/apps/validate

Pre-flight validation for App Intent JS and/or Solidity code.

Request body

  • bodyValidateAppRequest (required) (model ValidateAppRequest)
    • js_code: str = Field(..., description='JavaScript scoring code to validate')
    • solidity_code: str = Field('', description='Solidity contract code to validate')
    • skip_solidity: bool = Field(False, description='Skip Solidity compilation check')

POST /v1/apps/{app_id}/activate

Admin: promote an app from solving → active (for testing).

Path parameters

  • app_idstr (required)

Query parameters

  • chain_idint

GET /v1/apps/{app_id}/admin-state

Full operator view of an app for the management frontend.

Path parameters

  • app_idstr (required)

GET /v1/apps/{app_id}/auth-nonce

Next developer-auth nonce to sign for owner-gated actions on this app.

Path parameters

  • app_idstr (required)

Query parameters

  • deployerstr

POST /v1/apps/{app_id}/deploy

Deploy an App Intent to a specific chain (or first supported chain).

Path parameters

  • app_idstr (required)

Query parameters

  • chain_idint | None
  • waitbool
  • bodyDeployRequest | None

GET /v1/apps/{app_id}/deploy-quote

Quote the cost to deploy this App (#238): estimated gas per targeted chain

  • the deploy fee. Informational — gas is relayer-fronted today and the fee is not yet collected (public deployment is gated off until collection is live).

Path parameters

  • app_idstr (required)

Query parameters

  • chain_idint | None

PATCH /v1/apps/{app_id}/deployments/{chain_id}/config

Apply the relayer-gated on-chain config setters (V2 dex app).

Path parameters

  • app_idstr (required)
  • chain_idint (required)

Request body

  • bodyAppConfigRequest (required) (model AppConfigRequest)
    • fee_bps: int | None
    • volume_cap_bps: int | None
    • fee_collector: str | None

POST /v1/apps/{app_id}/deployments/{chain_id}/float/deposit

Fund the V2 app-held WETH fee float from the relayer wallet.

Path parameters

  • app_idstr (required)
  • chain_idint (required)

Request body

  • bodyFloatDepositRequest (required) (model FloatDepositRequest)
    • amount_wei: int = Field(..., gt=0)
    • wrap: bool = Field(True, description='Wrap relayer ETH into WETH first')

POST /v1/apps/{app_id}/deployments/{chain_id}/float/withdraw

Recover the V2 WETH float (relayer-gated withdrawFloat on-chain) — e.g. before retiring a deployment for a version migration.

Path parameters

  • app_idstr (required)
  • chain_idint (required)

Request body

  • bodyFloatWithdrawRequest (required) (model FloatWithdrawRequest)
    • to: str = Field(..., description='Recipient of the recovered WETH')
    • amount_wei: int = Field(..., gt=0)

GET /v1/apps/{app_id}/deployments/{chain_id}/registry-calldata

Prepared AppRegistry registerApp/revokeApp calldata for the current deployment. The revoke needs the registry OWNER key, which stays cold — the frontend surfaces this calldata for external signing.

Path parameters

  • app_idstr (required)
  • chain_idint (required)

POST /v1/apps/{app_id}/deployments/{chain_id}/registry/allow-developer

Owner-only AppRegistry.setDeveloperAllowed via the relayer key (which IS the registry owner today). Allowlisting the app’s real developer lets them registerApp/updateManifest from their own wallet — pair with GET …/registry-calldata.

Path parameters

  • app_idstr (required)
  • chain_idint (required)

Request body

  • bodyAllowDeveloperRequest (required) (model AllowDeveloperRequest)
    • developer: str = Field(..., description='Developer address to (dis)allow')
    • allowed: bool = Field(True)

POST /v1/apps/{app_id}/deployments/{chain_id}/retire

Mark a chain’s deployment RETIRED — releases the deploy guard so POST /apps/{app_id}/deploy performs an in-place redeploy (the deployment record upserts on (app_id, chain_id)). Store-only: recover any V2 WETH float FIRST via …/float/withdraw.

Path parameters

  • app_idstr (required)
  • chain_idint (required)

GET /v1/apps/{app_id}/historical-scenarios

Return PII-stripped historical filled-order scenarios for an app.

Path parameters

  • app_idstr (required)

Query parameters

  • n_per_chainint

POST /v1/apps/{app_id}/link-ss58

Link the app’s EVM deployer to a Bittensor SS58 coldkey (dual-signed).

Path parameters

  • app_idstr (required)

Request body

  • bodyLinkSS58Request (required) (model LinkSS58Request)
    • ss58: str = Field(..., description="The Bittensor SS58 coldkey to link as the app's payer.")
    • nonce: int = Field(0, description="Deployer's next developer-auth nonce (GET /apps/{id}/auth-nonce).")
    • deadline: int = Field(0, description='Unix-seconds expiry the EVM link_ss58 signature was signed with.')
    • evm_signature: str = Field(..., description='EIP-712 link_ss58 signature from the EVM deployer, binding (app_id, ss58, nonce, deadline).')
    • ss58_signature: str = Field(..., description="Substrate signature by the coldkey over 'MinotaurLinkSS58:{app_id}:{deployer_lower}:{nonce}' (hex).")

GET /v1/apps/{app_id}/manifest

Extract and return the JS manifest for an app.

Path parameters

  • app_idstr (required)

GET /v1/apps/{app_id}/payer-ss58

The Bittensor coldkey linked to this app’s deployer ("" if unlinked).

Path parameters

  • app_idstr (required)

POST /v1/apps/{app_id}/registration/approve

ADMIN approves registration: mark approved and register every deployed contract in the AppRegistry (admits it to live routing).

Path parameters

  • app_idstr (required)

POST /v1/apps/{app_id}/registration/reject

ADMIN rejects the registration request (→ rejected). On-chain state is untouched; the app stays deployed but out of live routing.

Path parameters

  • app_idstr (required)

Query parameters

  • bodyRejectRegistrationRequest | None

POST /v1/apps/{app_id}/registration/request

Owner submits a DEPLOYED app for registration review (unrequested → requested). Registration is what admits an app to the live order-routing set (on-chain _requireRegistered), so it is gated behind admin approval — this is the request half.

Path parameters

  • app_idstr (required)

Query parameters

  • bodyRequestRegistrationRequest | None

POST /v1/apps/{app_id}/score

Score an execution plan against an app’s JS scoring function.

Path parameters

  • app_idstr (required)

Request body

  • bodyScorePlanRequest (required) (model ScorePlanRequest)
    • plan: dict[str, Any] = Field(..., description='Execution plan to score')
    • params: dict[str, Any] = Field(..., description='Order params → state.raw_params')
    • chain_id: int = Field(0, description='Chain ID (0 = auto-detect from deployment)')
    • intent_function: str = Field('execute', description='Intent function name')
    • fork_block: int | None = Field(None, description='Optional historical block number to rewind the anvil fork to before simulating. Used by miner-side Stage-2 replay of historical filled orders so the plan is evaluated against the pool state at the time of the original order. Requires the upstream RPC to support archive reads.')

PUT /v1/apps/{app_id}/scoring

Update the JS scoring code for an App Intent.

Path parameters

  • app_idstr (required)

Request body

  • bodyUpdateScoringRequest (required) (model UpdateScoringRequest)
    • new_js_code: str = Field(..., description='New JavaScript scoring source')
    • caller: str = Field('', description='Deprecated, ignored. Authorization is by signature.')
    • signature: str = Field('', description="EIP-712 developer-auth signature from the app's deployer (required if a deployer was set). Binds action=update_scoring, app_id, keccak(new_js_code), nonce, deadline.")
    • nonce: int = Field(0, description="Deployer's next developer-auth nonce (GET /apps/{id}/auth-nonce). Must equal last_consumed + 1; consumed once on success.")
    • deadline: int = Field(0, description='Unix-seconds expiry the signature was signed with.')

PUT /v1/apps/{app_id}/solidity

Replace the stored contract source so the next deploy compiles it.

Path parameters

  • app_idstr (required)

Request body

  • bodyUpdateSolidityRequest (required) (model UpdateSolidityRequest)
    • solidity_code: str = Field(..., description='New contract source')
    • constructor_args: list[list[str]] | None = Field(None, description='Replacement ctor args: [[abi_type, value], ...]; omit to keep')
    • contract_version: str = Field('', description="New base generation ('v1'/'v2'); omit to keep")

GET /v1/apps/{app_id}/status

Get an App Intent’s status and execution statistics.

Path parameters

  • app_idstr (required)