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
| Item | In-head |
|---|---|
| Endpoint | POST /v1/cosign, as on layer 1 |
| Extra fields | context.hydraHeadId (56 hex) and context.hydraSnapshot. Send both or neither |
| Intents | Exactly one |
walletUtxoRef | Optional and ignored |
| Wallet value and datum | From the verified snapshot, not from Cardano |
| Body | One input, fee 0, exactly two outputs (continuing output and one escrow), no change output |
| Mandate and budget | The 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.
| Rule | How it is set |
|---|---|
Any party equals a key in the wallet's hydraParties | At registration; raw 32-byte Ed25519 keys in hex |
| Every party is on Exchain's list for your node | Ask 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.
| Check | Detail |
|---|---|
| Every party's Ed25519 signature over the snapshot | hydra_signature |
| The wallet output holds the state token at the registered address, with a valid datum | hydra_state_token, hydra_address, hydra_wallet_datum |
| The state token is not being decommitted | hydra_decommit |
| The commitment hashes to the accumulator | hydra_commitment |
| KZG membership of the wallet output | hydra_membership |
The proof must be canonical (lowercase hex, no leading zeros, no duplicate keys), otherwise 400.
Request
{
"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
| Rule | Behaviour |
|---|---|
| One window | In-head and layer 1 spends count in the same windows |
| Snapshot numbers never go back | A number below the highest accepted is refused utxo_unknown: snapshot_stale. An equal number is allowed |
| No layer 1 landing | An in-head signature is never marked landed on layer 1 |
| Budget returns when | A 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.