SpoolisDocs

Spoolis docs

Pay only what was earned

Reference flow: give an agent a spending ceiling, use Spoolis to determine what the work actually earned, then pay exactly that amount with the Outcome Receipt referenced.

This page documents a composed transaction we ran live on August 27, 2026: an agent wallet with an owner-controlled cap on Natural, a unitized Spoolis verification, and a payment for exactly the earned amount. No partnership is implied; the pattern works with any authorization layer that can cap spend and execute a payment.

The shape

authorize up to $1.00 → verify 100 units → 97 counted → $0.97 earned → pay exactly $0.97

Natural: authorization + payment · Spoolis: Outcome + earned value

The cap answers "how much may this agent spend?" The Outcome answers "how much did the work earn?"

Three responsibilities, two systems, one number crossing the seam. The payment platform answers "may this agent spend, and did the money move?". Spoolis answers "what did the work earn?". The earned amount and the signed receipt are the only contract between them.

1. Authorize the ceiling

Give the agent a wallet with a per-transaction cap at the agreed maximum. On Natural, spend limits are owner-controlled: the agent's own key cannot raise them, which is exactly the guardrail you want. The cap is the most the work can possibly cost; it is not what the work will earn.

2. Verify the delivered work

Submit the agreement and the delivered rows to one-call verification. Declare the unit count and per-unit price so partial results earn partial value.

Request
POST https://spoolis.com/api/v1/verify
Authorization: Bearer <your API key>
Content-Type: application/json

{
  "conditions": [{
    "description": "Each enrichment record passes the source URL, required field, and freshness checks",
    "deterministic_check": {
      "checker": "completeness",
      "required_fields": ["ok_source", "ok_fields", "ok_fresh"]
    }
  }],
  "max_amount_cents": 100,
  "unit": { "total_units": 100, "unit_amount_cents": 1 },
  "evidence": { "type": "dataset", "rows": [ /* 100 result rows */ ], "provenance": "uploaded_json" }
}
Response
{
  "accepted": 97,
  "rejected": 3,
  "earned_cents": 97,
  "rejections": [
    { "unit": 98, "reason": "ok_source is missing" },
    { "unit": 99, "reason": "ok_fields is missing" },
    { "unit": 100, "reason": "ok_fresh is missing" }
  ],
  "receipt": { "id": "ocr_..", "schema": "spoolis/outcome-receipt@1", "signature": ".." },
  "receipt_url": "https://spoolis.com/r/.."
}

Each rejected unit keeps a named reason, so a retry loop or a human can act on it. The signed Outcome Receipt binds the agreement, the evidence digest, the per-condition results, and the earned amount. See the Outcome Receipt specification.

3. Pay exactly the earned amount

Execute one payment for earned_cents, and put the receipt reference in the payment description so the money carries its own justification.

Payment
POST /payments on your payment platform

{
  "amount": 97,
  "currency": "USD",
  "counterparty": { "type": "email", "value": "seller@example.com" },
  "description": "Spoolis earned-value receipt: https://spoolis.com/r/.."
}

The live run

Our reference run: 100 records submitted, 97 accepted, 3 rejected with reasons, $0.97 earned against a $1.00 cap, one Natural payment of exactly $0.97 whose description references receipt ocr_cfd9006e6270239cf325b699. The verification half runs keylessly against the sandbox with the request shown above.

Integration notes

Practical notes from the live run: keep an idempotency key on every payment call; treat an email-addressed payment that is awaiting claim as created, not failed; and never let the paying agent raise its own cap. If your platform supports structured payment metadata, prefer it over the description field for the receipt link.

Pay only what was earned · Spoolis