Kaspa x402

Kaspa x402 Exact Binding v1

Status: draft

This document defines the Kaspa network binding for x402 v2 exact.

Summary

exact is for fixed-price one-shot purchases. The resource server knows the price before the request is served, and the client pays that exact amount for that request.

Use exact for:

Do not use exact for repeated micropayment sessions or variable-cost requests. Use batch-settlement for those.

Scheme and Network Pair

{
  "scheme": "exact",
  "network": "kaspa:<network>",
  "asset": "KAS",
  "extra": {
    "binding": "kaspa-exact-v1"
  }
}

Recognized draft network identifiers:

kaspa:mainnet
kaspa:testnet-10

kaspa:testnet-10 is the current alpha validation target. kaspa:mainnet is a reserved profile name, not a readiness claim.

PaymentRequirements

{
  "scheme": "exact",
  "network": "kaspa:testnet-10",
  "amount": "25000000",
  "asset": "KAS",
  "payTo": "kaspatest:...",
  "maxTimeoutSeconds": 60,
  "extra": {
    "binding": "kaspa-exact-v1",
    "finality": "accepted"
  }
}
FieldRequiredRule
schemeyesMust equal "exact".
networkyesMust be kaspa:mainnet or kaspa:testnet-10.
amountyesDecimal string in sompi. This is the exact payment amount.
assetyesMust equal "KAS".
payToyesRecipient Kaspa address for the selected network.
maxTimeoutSecondsyesMaximum time the client may take to provide a payment payload.
extra.bindingyesMust equal "kaspa-exact-v1".
extra.finalitynoOne of "mempool", "accepted", or "confirmed". If absent, servers choose local policy.

extra.finality is a server policy hint. It does not weaken validation. A server may require stronger finality than advertised, but should not require weaker finality than the value it advertises.

Lifecycle

1. Client requests a protected resource without payment. 2. Server returns x402 v2 PaymentRequired with an exact Kaspa entry in accepts. 3. Client builds a native Kaspa transaction paying amount sompi to payTo. 4. Client retries with PaymentPayload.accepted equal to the chosen requirements and payload.type = "exact-transfer". 5. Server or facilitator verifies the transaction. 6. Server or facilitator broadcasts or observes the transaction according to finality policy. 7. Protected resource is returned only after settlement policy succeeds. 8. Server returns SettlementResponse in the x402 transport response.

PaymentPayload

The payload type is exact-transfer.

{
  "type": "exact-transfer",
  "payerAddress": "kaspatest:...",
  "transaction": "<serialized transaction hex>",
  "transactionId": "<optional transaction id hex>",
  "paymentOutputIndex": 0,
  "requestHash": "<optional sha256 request fingerprint hex>"
}
FieldRequiredRule
typeyesMust equal "exact-transfer".
payerAddressnoClient payment address, if known. Used for receipts and policy only.
transactionyesSerialized Kaspa transaction hex.
transactionIdnoIf present, must match the id derived from transaction.
paymentOutputIndexyesIndex of the output that satisfies this payment.
requestHashnoSHA-256 of the normalized request fingerprint. Required when the server requires request binding.

The verifier must derive transaction identity and output data from transaction. Payload fields are hints until verified.

Transaction Requirements

The transaction must satisfy all of the following:

Change outputs are allowed. Additional unrelated outputs are allowed, but they do not satisfy this x402 payment.

Verification

Verification must reject with the relevant error code if:

SettlementResponse

Successful response:

{
  "success": true,
  "transaction": "<kaspa transaction id>",
  "network": "kaspa:testnet-10",
  "payer": "kaspatest:...",
  "amount": "25000000",
  "extensions": {
    "kaspa": {
      "paymentOutputIndex": 0,
      "finality": "accepted"
    }
  }
}

Failure response:

{
  "success": false,
  "errorReason": "invalid_transaction_state",
  "transaction": "",
  "network": "kaspa:testnet-10",
  "payer": "kaspatest:..."
}

Failure responses may include network only when the implementation can echo a valid canonical request network. Invalid, malformed, or unknown network failures must not synthesize a fallback network.

amount is the amount settled for this request. For exact, it must equal PaymentRequirements.amount on success.

Idempotency

Servers should advertise the x402 payment-identifier extension for exact. If it is required:

Even when payment-identifier is not required, the server must record consumed transaction ids to prevent the same transaction from buying multiple resources.

Security Notes

Toccata Notes

The base exact binding does not require a covenant. It may use an ordinary native Kaspa transaction.

If future exact flows use covenant-assisted sponsorship, they must still satisfy the x402 exact property: exactly one payment outcome for exactly the required amount to the required recipient.

Local Diagnostics

Public wire responses use the mapped reasons in errors.md. Implementations may use common invalid_kaspa_x402_* diagnostics plus:

invalid_kaspa_exact_transaction
invalid_kaspa_exact_transaction_id
invalid_kaspa_exact_payment_output
invalid_kaspa_exact_replay
invalid_kaspa_exact_finality

Source: /spec/kaspa-exact-v1.md