Attestra
Endpoints

Push

Write an already-signed attestation onto a target chain's own storage.

POST /v1/push

This endpoint writes an already-signed attestation onto a target chain's own storage, so other parties and their contracts can read it locally without calling Attestra. It is the only endpoint in this API that sends a blockchain transaction, and it is the only one that costs gas.

Request body

{
  "target": "ethr",
  "attestation": { "...": "as returned by Verify or Verify quorum" },
  "signatures": ["0x...", "0x..."]
}
FieldTypeRequiredDescription
targetstringyes"ethr", "eid", or "fabric". The chain to write to.
attestationobjectyesThe signed attestation to write.
signaturesarray of stringsyesOne or more signatures over the attestation's digest, ordered as described below.

signatures is an array, not a single value, because on-chain verification counts distinct authorized signers against a threshold; see the quorum rule. A legacy single signature string is still accepted and relayed as a one-element bundle. This is not a bypass: a one-signature bundle still has to clear the target's on-chain quorum check like any other bundle, and it only succeeds if that target's threshold is genuinely 1. When the threshold is higher, a one-element bundle is rejected on chain, which is the correct outcome, not a special case.

Signature ordering

Signatures must be ordered by recovered signer address, ascending. The target chain re-verifies each signature itself, recovers its signer, and requires each recovered address to be strictly greater than the last: this is what proves the signers are distinct and lets the chain count them in a single pass. See Verifying for why the ordering is required and what it defends against.

Verify quorum already returns its signatures array in this order, so the usual flow is to pass that array through to push unchanged, without re-sorting it.

Trust rests on the signatures, not the sender

Anyone may submit the push request: a relayer, the holder, or any other party who has the signed attestation and its signature bundle. The target chain verifies the signatures on chain and does not check who called this endpoint or who broadcast the resulting transaction. Possession of a quorum of valid signatures is what authorizes the write, not the identity of the caller.

Response

{
  "ref": "0x...",
  "target": "ethr"
}

ref is chain-specific. On Ethereum it is the transaction hash. On Hyperledger Fabric the pusher returns the literal string committed, because Fabric's submit call commits before it returns, so there is no separate hash to report.

A 502 does not mean nothing happened

This is the most important thing on this page.

push broadcasts the transaction and then waits to see it mined. If that wait fails, or the transaction is mined but reverts, the endpoint returns a bare 502. That 502 does not mean the write did not happen. Once a transaction is broadcast, everything after that point is a report on a real transaction, not a decision about whether to send one. A 502 can mean the transaction was broadcast and is still pending, or that it was broadcast and reverted. It never means the request was a no-op.

The error message carries a clue, but only sometimes. If the transaction was broadcast and the failure happened while waiting for it to be mined, the transaction hash is embedded in the message itself, in the form wait mined (tx 0x...); the hash is kept there because that is what an operator needs in order to look the transaction up. If the transaction was mined and then reverted, there is no hash in the message: the message says only that the push reverted.

The correct recovery is not to retry blindly. Retrying a push that actually landed produces a second, redundant transaction and spends gas twice. Instead, read the attestation back with Attestation and decide from what that read returns.

This has a real limitation worth stating plainly: read-back is implemented on Hyperledger Fabric only. On Ethereum, GET /v1/attestation returns 501 regardless of what happened to the push, so it cannot be used to resolve a push failure there. On Ethereum, the only route after a 502 is the transaction hash recovered from the error message, checked against a block explorer. On Hyperledger Fabric, read the attestation back directly and let that answer settle it.

Status codes

CodeMeaning
200The write succeeded. ref identifies the transaction or commit.
400Malformed request body, invalid signature hex, or no signatures supplied.
404No pusher is registered for the requested target.
502The write failed, or its outcome could not be confirmed. See above: this does not mean nothing happened.

Request bodies are capped at 1 MiB.

On this page