SpoolisDocs

Spoolis docs

Accept work between two parties

A Spool is a versioned acceptance policy for a piece of work. Use the bilateral lifecycle when both parties need to accept that policy inside Spoolis before work is verified.

When both parties agree in Spoolis

Use the bilateral lifecycle when both parties need to accept the agreement inside Spoolis. This path keeps agreement, acceptance, evidence submission, verification, and the receipt as separate inspectable steps.

Environment. Prefer /api/v1 for both environments. A sandbox session token selects isolated demo behavior with simulated settlement; a production API key selects production behavior. The /api/sandbox/* tree remains a working compatibility alias. This guide starts in the sandbox on purpose.

Who is doing the work? A person or business provider is paid through payout setup: the provider must finish payout onboarding before the buyer can fund. An agent or software provider is paid through the agent settlement path with wallet authority. In the API this choice is the Spool type field, and it defaults to service, the person or business path. Send type: "agent_task" for an agent or software provider. The creation response includes a lane block that states which path was selected.

Sandbox limits

Sessions are short-lived and have compile, Spool, verify, input-size, and record limits. Dataset evidence is limited to 100 records. Always inspect the stable code and status envelope, including on HTTP 200. If a session expires or reaches a limit, mint a fresh one and repeat the flow.

The MCP server also exposes sandbox scenarios, including the data enrichment flight scenario, through run_sandbox_scenario.

1. Mint a sandbox session

Run one request and keep the returned token.

terminal
curl -sS -X POST https://spoolis.com/api/sandbox/session > session.json

Expected checkpoint: session.json contains token, expires_at, and limits.
Keep: token.

2. Compile the agreement

Compile exact economics and two Live deterministic checks. See the single method-status table. Schema acceptance does not mean an executor is live.

terminal
TOKEN=$(node -p 'require("./session.json").token') && curl -sS https://spoolis.com/api/sandbox/compile -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"source":"A buyer pays for 100 enrichment records at $1.00 per accepted record, total $100.00. Exactly 100 records are required. Every record must include id and status.","economics":{"unitization":{"total_units":100,"unit_amount_cents":100}},"conditions":[{"description":"Exactly 100 records","required":true,"verification_method":"deterministic","deterministic_check":{"checker":"row_count","expected":100}},{"description":"Each record must include id and status","required":true,"verification_method":"deterministic","deterministic_check":{"checker":"completeness","required_fields":["id","status"]}}]}' > compile.json

Expected checkpoint: status is compiled and spool.environment is demo.
Keep: the Spool ID and both condition IDs.

3. Accept the sandbox Spool

Model acceptance in the sandbox.

terminal
TOKEN=$(node -p 'require("./session.json").token') && SPOOL_ID=$(node -p 'require("./compile.json").spool.id') && curl -sS -X POST "https://spoolis.com/api/sandbox/spools/$SPOOL_ID/accept" -H "Authorization: Bearer $TOKEN" > accept.json

Expected checkpoint: status is completed.
Keep: the same Spool ID.

4. Submit row-count evidence

Send 100 complete rows to the row-count condition.

terminal
TOKEN=$(node -p 'require("./session.json").token') && SPOOL_ID=$(node -p 'require("./compile.json").spool.id') && BODY=$(node -e 'const x=require("./compile.json");const condition_id=x.spool.conditions.find(c=>c.deterministic_check?.checker==="row_count").id;const rows=Array.from({length:100},(_,i)=>({id:"record-"+(i+1),status:"accepted"}));process.stdout.write(JSON.stringify({condition_id,type:"dataset",source:"100 enrichment records",metadata:{rows}}))') && curl -sS -X POST "https://spoolis.com/api/sandbox/spools/$SPOOL_ID/evidence" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d "$BODY" > count-evidence.json

Expected checkpoint: status is completed.
Keep: count-evidence.json for troubleshooting.

5. Submit completeness evidence

Send 98 complete rows and 2 rows missing status.

terminal
TOKEN=$(node -p 'require("./session.json").token') && SPOOL_ID=$(node -p 'require("./compile.json").spool.id') && BODY=$(node -e 'const x=require("./compile.json");const condition_id=x.spool.conditions.find(c=>c.deterministic_check?.checker==="completeness").id;const rows=Array.from({length:100},(_,i)=>i<98?{id:"record-"+(i+1),status:"accepted"}:{id:"record-"+(i+1)});process.stdout.write(JSON.stringify({condition_id,type:"dataset",source:"98 accepted and 2 rejected enrichment records",metadata:{rows}}))') && curl -sS -X POST "https://spoolis.com/api/sandbox/spools/$SPOOL_ID/evidence" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d "$BODY" > fields-evidence.json

Expected checkpoint: status is completed.
Keep: fields-evidence.json for troubleshooting.

6. Produce the Outcome

Run the acceptance step and save the signed receipt.

terminal
TOKEN=$(node -p 'require("./session.json").token') && SPOOL_ID=$(node -p 'require("./compile.json").spool.id') && curl -sS -X POST "https://spoolis.com/api/sandbox/spools/$SPOOL_ID/verify" -H "Authorization: Bearer $TOKEN" > lifecycle-verify.json && node -e 'const x=require("./lifecycle-verify.json");if(x.code||x.status==="limit_reached"||x.status==="resting")throw new Error(JSON.stringify(x));if(x.verdict!=="PARTIAL"||x.receipt.units.accepted!==98||x.receipt.units.rejected!==2||x.receipt.amounts.earned!=="98.00")throw new Error(JSON.stringify(x));require("node:fs").writeFileSync("bilateral-outcome-receipt.json",JSON.stringify(x.receipt,null,2)+"
")'

Expected checkpoint: verdict PARTIAL, 98 accepted, 2 rejected, and earned 98.00.
Keep: bilateral-outcome-receipt.json and its receipt ID.

Optionally check receipt status

This public, keyless endpoint adds correction, revocation, or advisory state. Receipt IDs are content-derived 96-bit values, so the lookup does not expose sequential identifiers. A well-formed ID with no known receipt returns state: "unknown" with HTTP 200.

terminal
RECEIPT_ID=$(node -p 'require("./outcome-receipt.json").id') && curl -sS "https://spoolis.com/api/v1/receipts/$RECEIPT_ID/status"

Expected checkpoint: a newly issued receipt reports state: "current". A replaced receipt reports state: "superseded" with its reason and, when available, the superseding receipt ID.

Spoolis maintains the acceptance state around the chosen judgment, determines what counted and what was earned, and signs the Outcome Receipt. A wallet, marketplace, payment system, or other workflow decides what happens next under its own policy.

Hand a production Spool to the counterparty

In production, a bilateral Spool reaches the other party through its share link, not through any hidden channel. The creation response includes share_url and a handoff block. Send share_url to the counterparty through any channel you already use: the link identifies the Spool, and the counterparty signs in on the web or accepts with their own API key to claim their side.

If you set a valid email address as the counterparty's contact, Spoolis also emails them the link. The handoff.invite_email field reports whether that email was sent, so never assume the other party was notified unless it says sent.

Move to production

Replace POST /api/sandbox/verify with POST /api/v1/verify and send a full-scope or verify-scoped production API key. Each account includes 10 verification runs and 10 free-text compiles per calendar month. Included usage is consumed first; paid compile and verification work then uses the prepaid usage balance. Transaction fees are separate. External settlement remains the default. Use managed settlement only with a full-scope key and a compatible configured payment path.

The bilateral path then forks on who does the work. Person or business provider: the provider finishes payout setup from the Spool page before the buyer can fund. Agent or software provider (type: "agent_task"): create a production API key, request production enablement for your account, then follow the wallet authority guide to register your principal, grant bounded authority with your own credentials, and verify the onchain permission. Enablement is an account status change, not a separate integration.

Agent with a wallet

POST https://spoolis.com/api/v1/verify/x402 is the keyless production door. Send the request without payment first. The 402 response quotes the exact price for that request in USDC on Base. Pricing varies with the verification work required, up to the published maximum.

  1. Send the request below with no payment. The response is HTTP 402 with a PAYMENT-REQUIRED header quoting the exact price for this request in USDC on Base (x402 v2, exact scheme). Send the request without payment first. The 402 response quotes the exact price for that request in USDC on Base. Pricing varies with the verification work required, up to the published maximum.
  2. Sign the quoted amount with an x402 client and retry the same request with the PAYMENT-SIGNATURE header.
  3. The same request now returns per-unit accepted/rejected/uncertain results, earned value for accepted units only, and a signed Outcome Receipt with a receipt id.
JSON
{
  "settlement": "external",
  "max_amount_cents": 3,
  "unit": {
    "total_units": 3,
    "unit_amount_cents": 1
  },
  "conditions": [
    {
      "description": "Every row includes status",
      "deterministic_check": {
        "checker": "completeness",
        "required_fields": [
          "status"
        ]
      }
    }
  ],
  "evidence": {
    "type": "dataset",
    "provenance": "api_response",
    "rows": [
      {
        "id": 1,
        "status": "complete"
      },
      {
        "id": 2,
        "status": "complete"
      },
      {
        "id": 3
      }
    ]
  }
}
Accept work between two parties · Spoolis