Skip to main content
Every upload is authenticated with a hotkey signature. The proxy reconstructs a canonical message from your request, verifies your signature against your hotkey, checks freshness and replay, and resolves your hotkey to a UID (src/platform_network/security/miner_auth.py:150-198). This page shows exactly what to sign.

Required headers

You send four headers on every signed upload (src/platform_network/security/miner_auth.py:159-162, docs/miner/README.md:90-95):
X-Hotkey: <miner-hotkey>
X-Signature: <signature>
X-Nonce: <nonce>
X-Timestamp: <timestamp>
HeaderMeaningSource
X-HotkeyYour ss58 hotkey addresssrc/platform_network/security/miner_auth.py:159
X-SignatureSignature over the canonical messagesrc/platform_network/security/miner_auth.py:160
X-NonceUnique per-request value (replay protection)src/platform_network/security/miner_auth.py:161
X-TimestampUnix seconds, checked for freshnesssrc/platform_network/security/miner_auth.py:162-169
Any missing header fails with missing <header> (src/platform_network/security/miner_auth.py:230-234).

The canonical message

The signed message is built exactly as (src/platform_network/security/miner_auth.py:96-111):
platform-upload-v1:{netuid}:{challenge_slug}:{METHOD}:{path}:{hotkey}:{nonce}:{timestamp}:{body_hash}
Where:
  • netuid is 100 (src/platform_network/config/settings.py:12).
  • challenge_slug is the resolved challenge slug, for example agent-challenge or prism (src/platform_network/master/app_proxy.py:438).
  • METHOD is the uppercased HTTP method (src/platform_network/security/miner_auth.py:109).
  • path is the request path (src/platform_network/master/app_proxy.py:435).
  • hotkey, nonce, and timestamp are the same values as your headers (src/platform_network/security/miner_auth.py:171-179).
  • body_hash is the SHA-256 hex digest of the raw request body (src/platform_network/security/miner_auth.py:170).

How to sign

1

Compute the body hash

Take the SHA-256 of the exact bytes you will upload and hex-encode it (src/platform_network/security/miner_auth.py:170).
2

Assemble the canonical message

Concatenate the fields with the platform-upload-v1: prefix and colon separators, using netuid 100, the challenge slug, the uppercased method, the path, your hotkey, your nonce, your timestamp, and the body hash (src/platform_network/security/miner_auth.py:96-111).
3

Sign with your hotkey

Sign the message bytes with your hotkey keypair. Verification uses the substrate ss58 keypair verify (src/platform_network/security/miner_auth.py:114-121).
4

Encode the signature

Provide the signature as a hex string, with or without a 0x prefix (src/platform_network/security/miner_auth.py:222-227).
5

Set the headers and send

Set X-Hotkey, X-Signature, X-Nonce, and X-Timestamp, then POST the body (src/platform_network/security/miner_auth.py:159-162).

Freshness and replay

  • Freshness: a timestamp more than 300 seconds from server time fails with stale signature (src/platform_network/security/miner_auth.py:168-169, src/platform_network/config/settings.py:33).
  • Replay: each nonce is reserved per netuid, challenge, and hotkey; a reused nonce fails with nonce already used (src/platform_network/security/miner_auth.py:60-90). Nonces are retained for 86,400 seconds (src/platform_network/config/settings.py:34).
  • Timestamp format: a non-integer timestamp fails with invalid timestamp (src/platform_network/security/miner_auth.py:163-166).
The signature covers the body hash, so any change to the bytes you upload, including a re-zip with a different timestamp inside the archive, changes body_hash and invalidates the signature (src/platform_network/security/miner_auth.py:170-180). Sign the exact bytes you send.

Identity resolution

After the signature verifies, your hotkey is resolved to a UID from the metagraph (src/platform_network/security/miner_auth.py:183,200-219):
  • An unregistered hotkey fails with unknown hotkey (src/platform_network/security/miner_auth.py:213-215).
  • UID 0 is blocked and fails with blocked uid (src/platform_network/security/miner_auth.py:143,217-218).
Use only fake placeholder values in any examples you publish; the live header values are your real hotkey and a real signature (docs/miner/README.md:88-95).

Next steps

Submitting your work

Apply this signature to the upload endpoints.

Troubleshooting

Resolve signature and replay errors.