Register a project
Prerequisites: an active, verified developer enrollment, the worker uploaded, and a manifest. The examples use
the necter_dev.py helper from Sign in and enroll.
-
Validate with
prepare. Send the unsigned manifest. Seteconomics.vaultto anything first; the response tells you the real predicted vault address.import jsonfrom necter_dev import api, login, personal_sign, sign_typedtok = login()manifest = json.load(open("manifest.json"))p = api("POST", "/v1/developers/projects/prepare", tok, json={"manifest": manifest})if p.get("vault"):manifest["consensus"]["economics"]["vault"] = p["vault"]p = api("POST", "/v1/developers/projects/prepare", tok, json={"manifest": manifest})for problem in p["problems"]:print(problem["path"], problem["code"], problem["message"])assert p["valid"]A valid response carries
canonical(the exact UTF-8 text to sign),manifest_hash,consensus_hash,project_id,vaultandtier_changes. -
Sign the canonical bytes with the developer wallet (
personal_sign, EIP-191) and build the envelope:envelope = {"manifest": manifest,"manifest_hash": p["manifest_hash"],"consensus_hash": p["consensus_hash"],"project_id": p["project_id"],"sig_type": "eip191","signature": personal_sign(p["canonical"]),} -
Submit it.
r = api("POST", "/v1/developers/projects", tok, json=envelope)project_id = r["project"]["project_id"]The response holds
register_tx(an ordinary transaction you could send yourself) andregister_by_sig(a gasless payload, valid for one hour). -
Register on-chain without gas. Sign the EIP-712
Registertyped data and post it back; the Hub’s relayer callsProjectRegistry.registerBySig.td = r["register_by_sig"]["typed_data"]status = api("POST", f"/v1/developers/projects/{project_id}/register", tok,json={"typed_data": td, "signature": sign_typed(td)})print(status) # {"status": "queued" | "sent" | "confirmed", "tx_hash": "0x…"}If the hour passed, get fresh payloads with
GET /v1/developers/projects/{project_id}/register-payload. -
Wait for indexing and review. Once the Hub indexes
ProjectRegistered, the project moves topending_review. Check withGET /v1/projects/{project_id}(listing_status) orGET /v1/developers/me/projects. On the testnet the network operator reviews and lists it.
Meanwhile, create and fund the vault: Vault, reward token, funding. You can also run up to 10 sample tasks through validators before the listing goes live:
sim = api("POST", f"/v1/developers/projects/{project_id}/simulations", tok, json={"tasks": [{"function": "work", "input": {"seed": "0x" + "ab" * 32, "seq": 0}}]})print(api("GET", f"/v1/developers/projects/{project_id}/simulations/{sim['simulation_id']}", tok))Common errors
Section titled “Common errors”Status / error |
Cause |
|---|---|
422 invalid_manifest |
A field breaks a rule; details.problems lists each one with its path |
422 invalid_manifest “a new project starts at version 1” |
version must be 1 and previous null for a new project |
409 already_exists |
This developer already has a project with this slug |
403 not_enrolled / 403 not_verified |
Finish enrollment first |
409 invalid_state “project is already registered on chain” |
Registration already went through |
400 on /register |
The typed data was not signed by the developer, or the payload expired |