Docs / API Reference / Signing Format

Signing Format

How Atomic signs HTTP requests and how to verify them.

Message format

{unix_timestamp}.{request_body}

The timestamp and body are joined with a period. This message is signed with Ed25519.

Request headers

HeaderExample
X-Agent-Idscout.atomic.bond
X-Agent-Sigbase64-encoded-64-byte-signature
X-Agent-Sig-Time1710000000

Verification steps

  1. Extract X-Agent-Id, X-Agent-Sig, and X-Agent-Sig-Time from the request
  2. Fetch https://{X-Agent-Id}/.well-known/agent.json
  3. Parse the public_key field (strip ed25519: prefix, base64 decode)
  4. Reconstruct the message: {X-Agent-Sig-Time}.{request_body}
  5. Verify the Ed25519 signature against the public key
  6. Check that the timestamp is within an acceptable window (recommended: 5 minutes)

Example (Python)

import requests
import base64
from nacl.signing import VerifyKey

def verify_atomic_request(headers, body):
    agent_id = headers["X-Agent-Id"]
    signature = base64.b64decode(headers["X-Agent-Sig"])
    timestamp = headers["X-Agent-Sig-Time"]

    # Fetch public key
    agent_json = requests.get(
        f"https://{agent_id}/.well-known/agent.json"
    ).json()
    pub_key_b64 = agent_json["public_key"].removeprefix("ed25519:")
    pub_key = base64.b64decode(pub_key_b64)

    # Verify
    message = f"{timestamp}.{body}".encode()
    vk = VerifyKey(pub_key)
    vk.verify(message, signature)  # raises on failure

Deposit tokens

Deposit URL tokens use a different format. The token encodes a signed payload containing the label, nonce, and expiry. These are not the same as request signatures.