capcomp submissions

Where miners on subnet 103 send recipes. Your recipe stays private until the run that pays it opens, so nobody can copy it while it is being measured.

How it works

Submitting here is the whole process. There is no on-chain step — no commitment, no transaction, no fee. You need a registered hotkey and a signature, nothing more.

Your recipe is held privately and published 2 runs later, once copying it can no longer help anyone: submitted in run N, measured in N+1, paid in N+2.

route
POST /submitSend a recipe. Up to 3 per run.
GET /status/{hotkey}How many attempts you have left this run.
GET /run/{id}A run's submissions. Bodies appear 2 runs on.
GET /contractThe same rules, machine-readable.
GET /docsFull API reference.

For validators

Submissions are not written to a public ledger, so this service is the record. Everything needed to check a run is served here, and all of it opens at the same moment — the run that pays it, 2 runs after the one submitted in.

GET /run/{id}What was submitted, and by whom.
GET /run/{id}/resultsEvery score, gate verdict and rank.
GET /run/{id}/weightsWhat the run pays, and whether it sums to one.
GET /run/{id}/instances/{hotkey}The per-instance record: what each package was asked, what it answered, what counted.

A run asked for before it opens answers with released: false and the run it opens in, rather than an error.

The limit

3 submissions per hotkey per run. Only your last one is measured, and only it is stored. Re-sending an identical recipe does not cost an attempt, so retrying a request that timed out is safe.

Signing

Sign this exact string with your hotkey, where the digest is sha256 over the precise bytes you send as recipe:

capcomp-submit:v1:<run_id>:sha256:<hex>

The run is taken from the chain by this service, so read it from /status/<your hotkey> first. Recipes are capped at 262,144 bytes.

import hashlib, json, requests
from bittensor_wallet import Wallet

API = "https://api.capcomp.ai"
wallet = Wallet(name="miner", hotkey="default")
body = json.dumps(my_recipe)          # exactly these bytes are hashed
sha = "sha256:" + hashlib.sha256(body.encode()).hexdigest()

run = requests.get(f"{API}/status/{wallet.hotkey.ss58_address}").json()["run_id"]
sig = wallet.hotkey.sign(f"capcomp-submit:v1:{run}:{sha}".encode()).hex()

print(requests.post(f"{API}/submit", json={
    "hotkey": wallet.hotkey.ss58_address, "recipe": body, "signature": sig,
}).json())

If it is refused

401The signature does not match. Check the run id and that you hashed the exact bytes you sent.
403That hotkey is not registered on subnet 103.
429You have used all 3 attempts this run.
503The chain is briefly unreachable. Retry shortly — this is never a rejection of your recipe.