Documentation

Integrate in one call

Ratchet has one important endpoint. Everything else exists to support it.

Machine-readable: OpenAPI · llms.txt · capability manifest · MCP tool schemas

1. Get a key

One request creates a workspace, seeds starter policies, and returns a key. The key is shown once and stored only as a keyed hash.

Or use the console if you'd rather click.

2. Ask before you act

Branch on decision. This is the whole contract.

DecisionMeaningWhat you must do
execute You hold the lease. Perform the action, then report.
duplicate Already completed. Use result. Do not act.
in_flight Someone else holds a live lease. Wait retry_after_seconds, ask again.
blocked A prior attempt's outcome is unknown. Verify at the vendor, then resolve.
approval_required Operator decision pending. Poll, or wait for the webhook.
denied Policy, budget, or rejection. Report the reason. Do not work around it.

3. Report what happened

The one rule that matters. Report failed only when you know the action did not reach the outside world. If you are unsure — a timeout, a dropped connection, an ambiguous error — report nothing. The lease lapses and Ratchet records an honest indeterminate. A false failed is worse than silence, because it licenses a duplicate.

Designing idempotency keys

The key is the entire mechanism. Derive it from the work, deterministically, so a retry of the same logical action produces the same key.

Good

  • welcome-email:user_123
  • invoice:2026-08:acct_88123
  • pr:acme/api:feature-auth
  • refund:order_551:full

Broken

  • uuid4()
  • "send-" + Date.now()
  • str(random.random())
  • f"job-{attempt_number}"

A key that changes on every attempt makes every retry look like new work. The gate can only recognise a duplicate if the duplicate says the same thing.

Reusing one key for genuinely different arguments is rejected with idempotency_key_reuse — that collision would otherwise hide a real, distinct action behind an unrelated record.

Policy: what happens when things go wrong

Configured per effect type. The default for an unconfigured type is the safe one.

FieldValuesEffect
modeallow · require_approval · deny Whether the type may run at all, and whether a human gates it.
on_indeterminateblock · retry · probe The important one. What a later caller may do when a prior attempt's outcome is unknown. Defaults to block.
lease_seconds5–3600 How long a holder has to report before the effect goes indeterminate.
max_attempts1–50 Ceiling on attempts for one key. Exceeding it denies the effect.
max_cost_microsinteger · null Refuse a single effect declaring more than this.
daily_budget_microsinteger · null Daily external-spend ceiling for this type.
retention_days1–400 How long records and replayable results are kept.

Choose retry only when the underlying vendor is genuinely idempotent, or a duplicate is truly harmless. Ratchet will not assume that for you.

Recovering an indeterminate effect

Check the vendor, then record what you found. This is what unblocks the key.

Subscribe to effect.indeterminate to be told the moment one appears, or poll GET /v1/effects?state=indeterminate.

Reversible effect groups

Rolling back a multi-step workflow

Declare several effects as one unit of work, and how to undo each. If the unit fails, Ratchet returns the exact compensation plan.

Then perform the plan

Each undo is itself gated. Use the suggested_idempotency_key and set compensates_effect_id. That is what stops a retried rollback from refunding twice — the failure that makes hand-rolled compensation dangerous.
Group stateMeaning
openAccepting steps.
committedEvery step succeeded. Can still be unwound later.
unwindingRolling back. Refuses new forward steps.
unwoundEverything reversible was reversed.
unwind_failedA step that succeeded had no compensation. Not a clean rollback, and it will not claim to be.

Read unresolved before acting on a plan. If any step's outcome is unknown, the rollback stops until you verify it — rolling back past a maybe is how a half-undone state is created.

Payments

Card, or crypto without custody

Subscribe with a card, or top up prepaid credit on-chain.

  • Non-custodial. Ratchet holds no private key. Payments go directly to an address the operator controls; Ratchet only watches the chain.
  • Quoted in USD. Credit granted is the USD amount, never the token amount, so a price move between quote and settlement cannot mint credit.
  • Underpayment is never rounded up. A short transfer credits nothing and waits for a human.
  • Volatile assets are refused unless a price oracle is configured. Quoting one without a live rate would mean inventing a price.

MCP

Nine tools over stdio or streamable HTTP, backed by the same code as the REST API.

Works today with Claude Code, Claude Desktop, Cursor, and any MCP client — see Get started for each. OpenAI-compatible tool loops and Gemini-style clients use the REST API directly.

Not listed in any provider directory. Ratchet is not submitted to, reviewed by, or endorsed by Anthropic, OpenAI, Google, or anyone else. One-click connector directories expect OAuth 2.1 with dynamic client registration; this endpoint uses a static bearer key, so installation is a config file you edit. That is honest about where it stands rather than implying a listing that does not exist.

Loading tool list…

Connecting

Errors

Every failure returns {"error": {"code", "message", "detail"}}. Branch on code; it is stable.

StatusCodeMeaning
400invalid_requestSchema validation failed. detail.validation says where.
401unauthorizedMissing, malformed, or revoked key.
402insufficient_creditAllowance exhausted and balance too low. Replays still work.
403forbiddenMissing scope. detail.required names it.
403budget_exceededA daily spend ceiling would be breached.
403cost_ceiling_exceededDeclared cost exceeds the per-effect maximum.
404not_foundNo such record in this workspace.
409idempotency_key_reuseSame key, different payload.
409lease_lostYour lease was superseded. Do not assume your work counted.
409invalid_stateThe transition is not legal from the current state.
413payload_too_largeStore large outputs elsewhere; record a reference.
429rate_limiteddetail.retry_after_seconds says how long to wait.