Skip to content

Classifier & refund policy

Every call gets one of three labels. The label decides whether the agent pays the premium, the provider keeps the principal, or the pool refunds the agent. Pact only earns on successful calls; failures are net $0 for the protocol.

  • success — call worked, agent pays, Pact earns the premium.
  • client_error — agent’s fault, no refund, Pact stays out of it.
  • server_error — provider/network’s fault, agent gets refunded (principal + premium).

The classifier runs at Market on the response from the upstream provider.

  • HTTP 200299.
  • Body is valid JSON or matches the upstream’s documented content type.
  • No body-level error sentinel flagged by EndpointConfig. (Some providers return 200 with {"error": "..."} — we treat known patterns as server_error.)
  • HTTP 400, 401, 403, 404, 405, 409, 410, 413, 415, 422, 429.
  • Pact-side rejections: bad API key, allowlist miss, payload too large.
  • Anything Market returns before reaching upstream (except 5xx bugs in Market — those are server_error).
  • HTTP 500, 502, 503, 504.
  • Upstream unreachable, connection reset, TCP/read timeout.
  • Truncated or malformed body on a 200.
  • Market internal 5xx (we eat the cost when our proxy breaks).
  • Schema validation. A 200 with a semantically wrong body (e.g. balance: -1) is still success.
  • Latency thresholds. Slow-but-eventually-200 is success.
  • Cross-call correlation. Each call is classified independently.

Principal = the x402 / MPP amount Market forwarded to the upstream. Premium = Pact’s per-call fee on top, set per EndpointConfig.

For a $0.01 upstream call with a 50 bps premium: principal = $0.0100, premium = $0.00005, total agent cost = $0.01005.

ClassificationAgent netUpstream netPool netPact net
success-principal -premium+principal+premium+premium
server_error$0.000$0.000-refund-out$0.000
client_error-principal+principal$0.000$0.000

On server_error, the agent gets back principal + premium. The provider doesn’t get paid (Market holds the principal in escrow or pulls it back, depending on the upstream rail). On client_error, the provider keeps the money — the agent broke their own request, so Pact doesn’t cover it.

For one call settled in settle_batch:

if classification == success:
AgentWallet -= premium
CoveragePool += premium
elif classification == server_error:
CoveragePool -= (principal + premium)
AgentWallet += (principal + premium)
elif classification == client_error:
# nothing — no fund movement on Pact's side.

The principal-on-success case sits outside the program. Market handles the agent → provider transfer over x402 / MPP.

  1. Trust. Earning on failed calls would create pressure to classify as client_error when in doubt. Net-zero on failure leaves only the successserver_error axis — healthier alignment.
  2. Simplicity. One rule: refund returns principal and premium. No tiers, no fee schedule.

Rates live on EndpointConfig and never apply retroactively — each call uses the rate active at the time of the call.

No on-chain dispute path in v1. Misclassifications are a support ticket with the X-Pact-Call-Id from the response header.