ExchainDocs
DocsAPI

CosignHydra in-head payments (Cardano)

Hydra in-head payments (Cardano)

Co-sign Cardano purchases inside a Hydra head under the same mandate and budget as layer 1.

Hydra is a Cardano layer 2. This page applies to Cardano wallets only.

Co-sign a purchase inside a Hydra head with the same call, mandate and budget as Cardano layer 1. A signed snapshot proves the wallet's state.

Trusted heads only. Heads running hydra-node 2.4.1. In-head co-signing works only for heads Exchain trusts for your node.

Differences from layer 1

ItemIn-head
EndpointPOST /v1/cosign, as on layer 1
Extra fieldscontext.hydraHeadId (56 hex) and context.hydraSnapshot. Send both or neither
IntentsExactly one
walletUtxoRefOptional and ignored
Wallet value and datumFrom the verified snapshot, not from Cardano
BodyOne input, fee 0, exactly two outputs (continuing output and one escrow), no change output
Mandate and budgetThe same mandate and the same windows as layer 1

Head trust

Exchain reads the head's parties from its open-state datum on Cardano, never from your request. The head is trusted if either rule holds.

RuleHow it is set
Any party equals a key in the wallet's hydraPartiesAt registration; raw 32-byte Ed25519 keys in hex
Every party is on Exchain's list for your nodeAsk Exchain

A head Exchain cannot find, read or trust, or a closed head, is refused 409 utxo_unknown with detail hydra_head_unknown, hydra_head_unreadable, hydra_head_closed or hydra_head_untrusted.

Snapshot proof

Each failing check returns 409 utxo_unknown with the detail shown.

CheckDetail
Every party's Ed25519 signature over the snapshothydra_signature
The wallet output holds the state token at the registered address, with a valid datumhydra_state_token, hydra_address, hydra_wallet_datum
The state token is not being decommittedhydra_decommit
The commitment hashes to the accumulatorhydra_commitment
KZG membership of the wallet outputhydra_membership

The proof must be canonical (lowercase hex, no leading zeros, no duplicate keys), otherwise 400.

Request

cosign.json (in-head)
{
  "batchId": "00000000-0000-4000-8000-000000000001",
  "txBodyHex": "a6…",
  "intents": [{
    "purchaseId": "pur_0", "outputIndex": 0,
    "counterparty": "sellerVkeyHash:<56 hex>",
    "amount": "199000000", "asset": "lovelace",
    "jobHash": "blake2b_256:<64 hex>", "agentIdentifier": "<registry asset id>"
  }],
  "context": {
    "nodeId": "node_1", "orgId": "org_acme", "submittedAt": "2026-11-05T10:00:00Z",
    "hydraHeadId": "4e4e…4e",
    "hydraSnapshot": {
      "headId": "4e4e…4e", "version": 1, "number": 7,
      "accumulator": "<64 hex>", "commitment": "<96 hex>", "witness": "<96 hex>",
      "walletOutput": {
        "address": "addr_test1w…",
        "value": { "lovelace": "250000000", "<56 hex policy>": { "<name hex>": "1" } },
        "inlineDatumRaw": "d8799f…"
      },
      "utxoToCommit": null, "utxoToDecommit": null, "depositTxId": null,
      "signatures": ["<128 hex>", "<128 hex>"]
    }
  }
}

Send Idempotency-Key equal to batchId, as on layer 1. The 200 answer is the same as on layer 1.

Budget

RuleBehaviour
One windowIn-head and layer 1 spends count in the same windows
Snapshot numbers never go backA number below the highest accepted is refused utxo_unknown: snapshot_stale. An equal number is allowed
No layer 1 landingAn in-head signature is never marked landed on layer 1
Budget returns whenA later request proves the same wallet output at a higher snapshot after the signature's validity ended, or an identical rebuild of the same purchase replaces it

After fanout, the wallet output is an ordinary layer 1 UTxO at the same address. Its next spend is a layer 1 co-sign.

On this page