SpoolisDocs

Spoolis docs

API reference

The v1 API is a bearer-authenticated Spool resource. Production keys bind created Spools to your account.

OpenAPI document

Import the OpenAPI 3.1 document from https://spoolis.com/openapi.json. It describes the production and sandbox routes, operation IDs, request shapes, examples, and error schema.

Endpoint index

This compact index is rendered from openApiDocument.paths. Use OpenAPI for request and response schemas instead of treating this as a second schema.

Method and pathAuthEnvironmentPurposeGuide
POST /api/v1/keys/exchangeNoneProductionExchange an API key grantGuide
POST /api/v1/spoolsBearerProductionCreate a SpoolGuide
GET /api/v1/spools/{id}BearerProductionGet a SpoolGuide
POST /api/v1/spools/{id}/inviteBearerProductionCreate a counterparty invitationGuide
GET /api/v1/spools/{id}/eventsBearerProductionList Spool eventsGuide
POST /api/v1/spools/{id}/{action}BearerProductionAct on a SpoolGuide
GET /api/receipts/{id}/statusNoneProduction and demoGet Outcome Receipt statusGuide
POST /api/v1/attestations/verifyNoneProduction and demoVerify an attestationGuide
GET /api/sandbox/sessionBearerDemoGet sandbox session stateGuide
POST /api/sandbox/sessionNoneDemoMint a sandbox sessionGuide
POST /api/sandbox/compileBearerDemoCompile a sandbox SpoolGuide
POST /api/sandbox/spools/{id}/{action}BearerDemoAct on a sandbox SpoolGuide

Base URL and authentication

request
Authorization: Bearer spk_live_...
Content-Type: application/json

Create a production key on the API keys page. Creating a key requires sign-in, and the full key is shown once. Store it securely and send it as a bearer token. Missing, invalid, unknown, or revoked keys return 401. Static spk_test_ keys remain available in configured development and test environments.

Anyone can open and review a shared Spool. Accepting through the production API requires an authenticated key for a party to that Spool.

Machine counterparty exchange

The Spool initiator can call POST /api/v1/spools/{id}/invite with a full-scope key. The active Spool must have exactly one unassigned counterparty slot. The response shows a 15-minute, single-use grant token, its expiry, and the exchange URL.

The counterparty sends the grant token to POST /api/v1/keys/exchange as {"grant_token":"spg_..."}. The response shows a counterparty API key once. This key is agreement identity only. It can read its bound Spool, accept, decline, and submit evidence while the outcome is active. It cannot create or list Spools, list events, commit or fund settlement, run verification, or act on another Spool.

Funding and payout setup

Spoolis determines earned value and signs the Outcome Receipt. A wallet, marketplace, payment system, or configured integration may verify and consume it, then act under its own authorization and settlement policy.

The optional built-in path uses a configured settlement adapter. When Stripe Connect is configured for a production human transaction, the provider completes payout onboarding and the buyer opens hosted Checkout. That adapter creates a manual-capture authorization and acts on the verification result according to its policy.

Verification method request values

deterministic is Live, human_confirmed is Live, external_tool is Reserved, and ai_assisted is Planned. Schema acceptance does not mean an executor is live. Use the single method-status table when choosing a value.

Troubleshooting by stage

These names come from the REST error registry, receipt verifier, and MCP client. Always branch on the stable code or reason, not the HTTP status alone.

StageActual code or reasonLikely causeNext action
Sessionsession_expired, limit_reached, sandbox_resting, rate_limited, configuration_unavailableThe session expired, exhausted a budget, the shared sandbox is resting, rate is too high, or required configuration is unavailable.Mint a fresh session for expired or exhausted sessions. Otherwise inspect retryable and remediation, then wait before retrying.
Compileinvalid_json, input_too_large, ambiguity_required, validation_failed, compile_failedThe body is malformed, too large, missing an exact amount, fails a field rule, or cannot be compiled.Correct the named field or intent. Retry compile_failed only when retryable is true.
Lifecycleunauthenticated, forbidden, spool_not_found, unknown_action, invalid_state, store_conflictAuthentication, visibility, action name, lifecycle state, or a concurrent write blocked the request.Fix authentication or the action. Read the current Spool before retrying a conflict.
Settlementsettlement_unavailableThe requested managed settlement path is unavailable.Follow remediation or use an independently authorized external consumer.
Attestationtrusted_key_unavailable, internal_errorTrust configuration or the service prevented verification.Retry only when retryable is true. Do not treat the artifact as verified.
Receipt verifierunknown_schema, environment_mismatch, invalid_evidence_root, invalid_run_digest, invalid_agreement_hash, receipt_id_mismatch, earned_exceeds_committed, earned_amount_mismatch, aggregation_inconsistentThe receipt conflicts with the supported schema, caller environment, digests, ID, amounts, or aggregation rule.Reject the receipt and inspect the named invariant.
Receipt verifieruntrusted_signing_key, signing_key_id_mismatch, invalid_signature, malformed_receiptThe key is not trusted, the key ID differs, the signature fails, or the receipt cannot be parsed.Reject the receipt. Refresh only from reviewed trust material.
Online statuscorrected, revokedAn operator marked the authentic receipt corrected or revoked.Treat verifier policy as invalid and follow the advisory under your reconciliation policy. No payment is automatically reversed.
Receipt advisoriesstatus_source_unavailable, key_retiringNo online status was supplied, or the trusted key is retiring.Continue offline-only under caller policy, or review and pin the current published trust entry.
MCPproduction_key_required, sandbox_session_failedThe tool has no sandbox equivalent, or the MCP server could not mint its demo session.Configure SPOOLIS_API_KEY for a production-only tool, or mint a fresh sandbox session and retry.

Payment path selection

Payment path selection is fail closed. It considers the actor, amount, currency, configured adapters, declared machine capabilities, readiness, and demo mode. It returns an explicit refusal when no compatible production path qualifies. See Payment paths for the complete model and preview boundaries.

Create a Spool

POST /api/v1/spools

Returns the created canonical Spool with HTTP 201. The request is strict: unknown fields are rejected. This example represents a buyer's $100.00 maximum for 100 enrichment records at $1.00 per accepted record.

request.json
{
  "type": "agent_task",
  "parties": [
    { "role": "buyer", "kind": "agent", "display_name": "Buyer agent" },
    { "role": "provider", "kind": "service", "display_name": "Data provider" }
  ],
  "value": { "amount_cents": 10000, "currency": "USD" },
  "deliverable": {
    "type": "dataset", "title": "Enrichment records",
    "description": "100 enrichment records", "attributes": {}
  },
  "terms": [{
    "text": "100 enrichment records at $1.00 per accepted record",
    "provenance": { "source": "user_added", "origin": "user_added" }
  }],
  "conditions": [{
    "description": "Exactly 100 rows", "required": true,
    "verification_method": "deterministic",
    "deterministic_check": { "checker": "row_count", "expected": 100 }
  }]
}

Request fields

  • type: goods_in_person, service, digital, or agent_task. Defaults to service.
  • parties: exactly two unique display names. Roles are buyer, seller, client, or provider; kinds are human, agent, org, or service. Optional fields are contact, account_id, and a Stripe-style stripe_account_id.
  • value: positive integer amount_cents, literal currency USD, and optional rail_preference.
  • deliverable: required type, title, description, and string-to-string attributes.
  • terms: at least one item with text and provenance. Provenance source is listing, chat, image, freeform, or user_added.
  • conditions: an array with description, required flag, and verification method. Deterministic conditions must declare one checker: row_count, completeness, duplicate_rate, url_format, json_path, http_status, text_contains, hash_matches, or deadline_met.
  • economics: optional fee_cents and ISO datetime expiry.

Read a Spool

GET /api/v1/spools/{id}

Returns the canonical Spool. The economics.allowed_actions array is computed for the authenticated party. A share ID may also resolve here.

GET /api/v1/spools/{id}/events

Returns the canonical event array in recorded order.

Read and verify an Outcome Receipt

Continue the canonical example by verifying the delivered records. Spoolis accepts 98 records, rejects 2 with reasons, and returns a signed Outcome Receipt recording $98.00 earned. Verify that receipt outside the API with @spoolis/receipt-verifier and pinned receipt keys from the public trust set. Offline signature verification is sufficient. You may then call GET /api/receipts/{id}/status for {receipt_id, status: 'active', advisories: [], checked_at}. After verification and the optional status check, the payment stack may act on the $98.00 earned amount under its own authorization policy.

Verify the underlying attestation

POST /api/v1/attestations/verify

The attestation is the lower-level in-band signed verdict underneath the Outcome Receipt. Send the complete attestation JSON. This public endpoint checks the environment-specific trusted key, signature, digests, expiry, and amount bounds. It returns valid, environment, and machine-readable reasons. It never returns the submitted attestation.

Actions

Send POST /api/v1/spools/{id}/{action}. Lifecycle rules can reject actions that are unavailable in the current state.

ActionRequest bodyBehavior
proposeNo bodyMove agreement to proposed.
acceptNo bodyAccept a proposed agreement.
declineNo bodyDecline and cancel the outcome.
cancelNo bodyCancel the agreement and outcome.
abandonNo bodyLet either party cancel an active Spool before settlement is committed. Requires a full-scope key.
commit`payment_method?: string` beginning `pm_`Ask the configured settlement adapter to authorize and, where supported, hold.
evidence`condition_id`, `type`, `source`, optional `metadata`Submit evidence during fulfillment.
verifyOptional `confirmations` arrayRun verification and, when signing is configured, return an Outcome Receipt with its underlying attestation.
completeNo bodyRead a Spool whose outcome is already completed. This action does not run verification or settlement.
onboard-provider`refresh_url`, `return_url`Start provider onboarding only when the adapter supports it.

Evidence type is one of photo, text, file, url, dataset, or confirmation. Each verify confirmation contains condition_id, method buyer_confirm or both_confirm, outcome passed, failed, or waived, an evidence_refs array, and optional detail.

Errors and rate limits

Every v1 and sandbox error keeps the human-readable error and adds a stable code, retryable flag, and actionable remediation. When relevant, field identifies the failed field or condition path and docs links to help.

error.json
{"error":"Invalid API key","code":"unauthenticated","retryable":false,"remediation":"Provide a valid Spoolis API key in the Authorization header.","field":"headers.authorization","docs":"https://spoolis.com/docs/api"}
CodeStatusRetryableMeaning
ambiguity_required422NoThe request needs a missing exact value.
configuration_unavailable503YesA required service configuration is unavailable.
compile_failed422YesThe sandbox compiler could not compile the supplied intent.
forbidden403NoThe caller cannot access this resource or operation.
input_too_large413NoThe request exceeds a documented size limit.
internal_error500YesThe server could not complete the request.
invalid_json400NoThe request body is not valid JSON.
invalid_state409NoThe operation is unavailable in the current lifecycle state.
limit_reached200NoThe sandbox session has exhausted an operation budget.
rate_limited429YesThe request rate limit was reached.
sandbox_resting200YesThe shared daily sandbox budget is resting.
settlement_unavailable409YesThe requested managed settlement path is not currently available.
session_expired401YesThe sandbox session is missing or expired.
spool_not_found404NoThe requested Spool does not exist or is not visible to the caller.
store_conflict409YesThe Spool changed before the update was saved.
trusted_key_unavailable200YesThe attestation environment trust key is unavailable.
unknown_action404NoThe requested lifecycle action is not supported.
unauthenticated401NoValid authentication was not provided.
validation_failed400 or 422NoA request field or attestation failed validation.

The implemented v1 limit is 120 requests per minute per account or test-key party label and forwarded IP. A limited request returns 429 with a Retry-After header. When Upstash is not configured, the application currently allows requests without enforcement and logs a warning, so deployments must not assume the limit is active merely because it is documented here.

Binding condition rules

Conditions are binding only when the caller explicitly includes them. Compiler suggestions stay separate until a user or caller adds them. Terms and conditions with unresolved placeholders such as [amount], [date], or TBD are rejected with HTTP 422.

API reference · Spoolis