ZIFFER home

Quickstart

How an agent reaches ZIFFER - MCP, an SDK, or plain HTTPS - and what the first proposal and receipt look like.

Read this before you copy anything

The endpoints, package names and tokens on this page are placeholders. ZIFFER is not open for self-serve signup, so there is nothing yet to point them at, and no code below has been run against a live service. Every placeholder is marked. Write to hello@ziffer.io for access.

The agent edge

Three ways in. They carry the same proposal and get back the same receipt; the difference is what your agent already speaks.

EdgeUse it whenState today
MCP serverThe agent is a model with tool callingPlaceholder
SDKThe agent is your codePlaceholder
HTTPSAnything else, or a language with no SDKPlaceholder

MCP

The model gets one tool. It proposes; it does not decide.

mcp.json (PLACEHOLDER: endpoint not live)
{
  "mcpServers": {
    "ziffer": {
      "url": "https://mcp.example-placeholder.invalid/",
      "headers": { "Authorization": "Bearer PLACEHOLDER_TOKEN" }
    }
  }
}

The model must be shown complying, not refusing. A demo where the model declines the risky action proves nothing about ZIFFER: the guarantee is that the action does not run, and it holds whether or not the model cooperates.

SDK

propose.ts (PLACEHOLDER: package not published)
// import { ziffer } from '@ziffer/sdk';   <- not on npm yet

const decision = await ziffer.propose({
  action: 'refund.issue',
  resource: 'account/48812',
  arguments: { amount: '4200.00', currency: 'EUR' },
});

if (decision.outcome !== 'granted') {
  // Nothing ran. There is no partial state to undo.
  return;
}

await execute(decision.receipt);

execute takes the receipt, not a boolean. An executor that trusts a flag trusts the caller; an executor that verifies a receipt does not have to.

HTTPS

curl (PLACEHOLDER: host will not resolve)
curl -X POST https://api.example-placeholder.invalid/v1/proposals \
  -H "Authorization: Bearer PLACEHOLDER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "action": "refund.issue",
        "resource": "account/48812",
        "arguments": { "amount": "4200.00", "currency": "EUR" }
      }'

What comes back

One of three shapes.

Granted. A receipt. Verify it, then act.

Held. The action met a floor and needs a quorum. Your agent gets no receipt and must not proceed.

held - quorum 2-of-2 required

Refused. The action is outside policy, or policy has nothing to say about it. An action with no risk function is refused rather than graded down, so a gap in policy stops the action instead of quietly permitting it.

Verify before you execute

The last step is the one that matters. Check the receipt against the signed policy you already hold. Do not read the outcome out of the message and believe it.

verify.ts (PLACEHOLDER: package not published)
const ok = await ziffer.verify(receipt, { bundle });
if (!ok) throw new Error('receipt did not verify');

Both signature algorithms must verify. Either one alone is not a pass.

Next

  • Concepts: proposal, grant, quorum, receipt, anchor.
  • Verify the claims: the open specification, and how to replay it yourself.

On this page