About Claims

How claims describe what should happen inside an intent — each claim is a single instruction that the ledger prepares and commits atomically.

Audience: Technical Leaders, Developers · Read time: 6 min

Every intent needs to say what it wants done. Claims are how it says it. A claim is a single movement instruction nested inside an intent — it names a source, a target, an amount, a currency, and an action. When the ledger processes the intent, it executes each claim according to that instruction, coordinating across every system involved.

If an intent is a payment order, a claim is one line item in that order.

What a claim is

A claim is the most concrete thing in the Minka data model. It names exactly four things: who gives, who receives, how much, and in what currency. "Transfer 150,000 COP from treasury@bank.co to chk:98765@yourbank.co" is one claim. There is no ambiguity, no policy to interpret, no routing decision to make at the claim level — the claim just describes the desired outcome.

The ledger figures out how to make that outcome happen. Whether the two wallets are at the same institution or different ones, whether the movement crosses one network or several, whether the target is on a domestic real-time rail or an international wire network — none of that changes what the claim looks like. The claim describes the result; the ledger owns the means.

This separation is what makes intents portable. The same claim structure that works for a domestic peer-to-peer transfer also works for an interbank settlement or a cross-border disbursement. You describe what should happen, not how it should happen.

The claim structure

Every claim has five fields.

{
  "action": "transfer",
  "amount": "15000000",
  "symbol": { "handle": "cop" },
  "source": { "handle": "treasury@bank.co" },
  "target": { "handle": "chk:98765@yourbank.co" }
}

action says what kind of movement this is. amount is the quantity in the smallest unit of the currency — so 15000000 represents 150,000.00 COP, not 15,000,000 COP, because COP uses two decimal places. symbol identifies the currency by its handle. source and target identify the wallets using the standard schema:number@domain addressing format — see About Wallets for how wallet addresses are structured.

Both source and target carry a handle field because they reference ledger objects by their registered identifier. The ledger resolves these handles at execution time, looking up the actual wallet records, their current balances, and any associated bridges that need to coordinate.

The amount field is always an integer. There are no floating-point numbers in the Minka data model. This eliminates an entire class of rounding errors that commonly appear when financial systems mix integer and floating-point representations mid-transaction.

Action types

transfer is the primary claim action — it moves value from the source wallet to the target wallet, debiting one and crediting the other. This covers the vast majority of payment scenarios: person-to-person transfers, business disbursements, merchant settlements, interbank movements.

The action model is designed to be extensible. As the platform evolves, additional action types can express other kinds of ledger operations within the same claim structure. For most use cases today, transfer is the action you will use.

Multi-claim intents

A single intent can carry multiple claims, and this is where the model becomes genuinely powerful.

Consider a marketplace payment where a customer's 100,000 COP purchase needs to be split: 95,000 to the seller's settlement wallet and 5,000 to the platform's fee account. You could submit two separate intents, but then you have a consistency problem — what if the first completes and the second fails? Now the seller has been paid but the platform hasn't collected its fee.

With two claims in a single intent, that problem disappears. Either both movements happen or neither does. The same logic applies to payroll runs: a disbursement batch with hundreds of employee payments can be expressed as hundreds of claims in one intent. If the funding account doesn't have enough balance to cover them all, the entire batch fails to prepare and nothing is debited. There is no partial payroll, no reconciliation ticket, no manual cleanup.

Multi-claim intents are also how currency exchange works. A cross-currency payment might debit pesos from one wallet, credit dollars into another, and adjust a settlement account to reflect the exchange — three claims, one intent, one atomic outcome.

The claims array inside an intent has no practical upper bound for routine use. The ledger evaluates each claim and reserves the necessary funds during the prepare phase before committing any of them.

Consider a concrete example. A marketplace order for 100,000 COP needs to split: 95,000 to the seller and 5,000 to the platform fee account.

{
  "handle": "marketplace-order-9821",
  "claims": [
    {
      "action": "transfer",
      "amount": "9500000",
      "symbol": { "handle": "cop" },
      "source": { "handle": "escrow@marketplace.co" },
      "target": { "handle": "svgs:42424242@seller-bank.co" }
    },
    {
      "action": "transfer",
      "amount": "500000",
      "symbol": { "handle": "cop" },
      "source": { "handle": "escrow@marketplace.co" },
      "target": { "handle": "fees@marketplace.co" }
    }
  ],
  "config": { "commit": "auto" }
}

Both claims execute atomically. If the escrow account lacks sufficient funds for the full 100,000 COP, neither the seller payment nor the fee collection happens — the entire intent is rejected and the escrow balance remains untouched.

Claims and the two-phase commit

Each claim participates in the intent's two-phase commit protocol. Understanding this relationship explains why the atomicity guarantee is real and not just a promise.

During the prepare phase, the ledger evaluates every claim and attempts to reserve the specified amounts. For a claim that crosses institutional boundaries, this means contacting the relevant bridge, which in turn contacts the destination system. Only when every participant — every bridge, every external system touched by any claim — has confirmed that it can honor its side does the prepare phase succeed. If any single claim cannot be prepared for any reason (insufficient balance, unreachable system, validation failure), the entire intent transitions to rejected and every reservation is released. Nothing has moved.

During the commit phase, all reservations become permanent. Every balance update across every system involved in every claim happens as a coordinated unit. This is the point of no return — once committed, the movements are final.

The consequence of this structure is that a multi-claim intent can never be partially executed. If you have an intent with ten claims and claim seven fails to prepare, all ten are rejected together. The books are balanced at the end of every failed intent exactly as they were at the beginning.

Claims vs. intents

The intent is the container. It carries a handle (the unique identifier and idempotency key), configuration like whether to auto-commit after prepare, and the claims array. The claims are the payload — the actual instructions the intent is asking the ledger to execute.

Think of the intent as the envelope and the claims as the letters inside it. The envelope has an address (the handle), instructions for the carrier (the config), and a postmark that ensures the same letter isn't delivered twice. The letters describe what actually needs to happen.

This separation matters when you're thinking about idempotency. The intent's handle prevents duplicate processing — if a network glitch causes your client to retry, submitting the same handle returns the original intent without processing it again. The claims inside that intent don't need their own idempotency mechanism because they're protected by the envelope that wraps them.

It also matters for observability. When you look up an intent by handle, you see its status (pending, prepared, committed, completed, rejected), its configuration, and the full claims array. Each claim's execution is reflected in the intent's overall status — there is no per-claim status to track separately.

Multi-claim intents

Most payments involve a single claim — one source, one target, one amount. But intents support multiple claims in a single array, and every claim in the array is executed atomically: either all succeed or none do.

This is how you model split payments, platform fees, and multi-party settlements without separate transactions. A merchant payment that also routes a service fee looks like this:

{
  "claims": [
    {
      "action": "transfer",
      "source": "svgs:wallet:merchant-store-001",
      "target": "svgs:wallet:bank-settlement",
      "symbol": "svgs:symbol:usd",
      "amount": "100.00"
    },
    {
      "action": "transfer",
      "source": "svgs:wallet:merchant-store-001",
      "target": "svgs:wallet:platform-fees",
      "symbol": "svgs:symbol:usd",
      "amount": "2.50"
    }
  ]
}

Both claims prepare together and commit together. If the fee wallet rejects the second claim — maybe a policy blocks the amount — neither transfer happens. The merchant's balance stays untouched. This atomicity guarantee holds regardless of how many claims the intent carries or how many bridges are involved in executing them.

Multi-claim intents also simplify reconciliation. Instead of correlating two separate intents that were "supposed to happen together," you have a single handle that represents the entire economic event. One intent, one status, one audit trail.

What's next

On this page