API Reference

Arbiter provides a REST API for submitting disputes, registering agents, and retrieving resolutions in multi-agent transaction chains. All requests and responses use JSON.

Base URL

base url
https://arbiter-2.polsia.app

All endpoints are relative to this base URL. TLS is required — HTTP requests are not accepted.

Authentication

Arbiter uses API key authentication. Pass your API key as a Bearer token in the Authorization header on every request.

http
Authorization: Bearer arb_live_your_api_key_here

The API is currently in open beta. Authentication is enforced for production traffic. Keep your API key secret — treat it like a password. Never commit it to source control.

API Key Prefixes

PrefixEnvironmentDescription
arb_live_ production Live disputes — real resolution logic applied
arb_test_ sandbox Test disputes — no real settlement, safe for integration testing

Quick Start

Submit your first dispute in 3 API calls.

1
Register your agents

Before submitting a dispute, register each agent involved in the transaction chain.

curl
curl -X POST https://arbiter-2.polsia.app/api/agents \
  -H "Authorization: Bearer arb_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "external_agent_id": "agent-buyer-001",
    "name": "BuyerBot",
    "platform": "sapiom",
    "sla_policy": { "refund_window_hours": 24 }
  }'
2
Submit a dispute with the transaction chain

Include every hop in the chain — who initiated, who was subcontracted, and where delivery broke.

curl
curl -X POST https://arbiter-2.polsia.app/api/disputes \
  -H "Authorization: Bearer arb_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Agent C delivered corrupt data payload",
    "chain_data": [
      {
        "agent_id": "agent-buyer-001",
        "action": "initiated_purchase",
        "timestamp": "2026-04-23T10:00:00Z",
        "amount": 150.00
      },
      {
        "agent_id": "agent-fulfiller-002",
        "action": "accepted_subcontract",
        "timestamp": "2026-04-23T10:00:05Z"
      },
      {
        "agent_id": "agent-data-003",
        "action": "delivered_output",
        "timestamp": "2026-04-23T10:01:30Z",
        "outcome": "failed",
        "error": "null_payload"
      }
    ]
  }'
3
Check the resolution

Poll the resolution endpoint until the dispute status is resolved. Resolution typically completes within seconds.

curl
curl https://arbiter-2.polsia.app/api/disputes/1/resolution \
  -H "Authorization: Bearer arb_live_..."

Agents

POST /api/agents Register an agent

Register an agent with an optional SLA policy. Once registered, an agent can be referenced in dispute submissions. Agents are deduplicated by external_agent_id.

Request Body

FieldTypeRequiredDescription
external_agent_id string required Your unique identifier for this agent. Max 255 chars.
name string required Human-readable name. Max 255 chars.
platform string required Platform this agent operates on (e.g. sapiom, stripe-acp, coinbase-x402). Max 255 chars.
sla_policy object optional SLA terms applied during fault determination. Free-form JSON object. E.g. { "refund_window_hours": 24, "max_retry_attempts": 3 }.

Response

201 Created
{
  "id": 42,
  "external_agent_id": "agent-buyer-001",
  "name": "BuyerBot",
  "platform": "sapiom",
  "sla_policy": { "refund_window_hours": 24 },
  "created_at": "2026-04-23T10:00:00.000Z"
}

Status Codes

201 Created 400 Validation error 409 Duplicate external_agent_id 500 Server error
GET /api/agents List agents

Returns all registered agents, sorted by registration date descending. Optionally filter by platform.

Query Parameters

ParameterTypeRequiredDescription
platform string optional Filter by platform name. Exact match.

Example

curl
curl "https://arbiter-2.polsia.app/api/agents?platform=sapiom" \
  -H "Authorization: Bearer arb_live_..."

Response

200 OK
{
  "agents": [
    {
      "id": 42,
      "external_agent_id": "agent-buyer-001",
      "name": "BuyerBot",
      "platform": "sapiom",
      "sla_policy": { "refund_window_hours": 24 },
      "created_at": "2026-04-23T10:00:00.000Z"
    }
  ],
  "count": 1
}

Status Codes

200 OK 500 Server error

Disputes

POST /api/disputes Submit a dispute

Submit a dispute with the full transaction chain. Arbiter traces the chain to determine fault and enqueues the dispute for resolution. The dispute starts with status open.

Request Body

FieldTypeRequiredDescription
chain_data array required Ordered array of transaction hops. Each hop requires agent_id, action, and timestamp.
description string optional Human-readable description of the dispute.
submitter_agent_id integer optional Arbiter id of the agent submitting this dispute. Must exist — register first via POST /api/agents.
fault_agent_id integer optional Arbiter id of the agent believed to be at fault. If omitted, Arbiter determines fault from the chain.

Chain Hop Object

FieldTypeRequiredDescription
agent_id string required Your external agent identifier.
action string required What this agent did at this hop (e.g. initiated_purchase, delivered_output, failed_delivery).
timestamp string required ISO 8601 timestamp of the action.
amount number optional Dollar value of this hop (for settlement calculations).
outcome string optional success or failed.
error string optional Error code or message if outcome is failed.
metadata object optional Arbitrary additional context for this hop.

Response

201 Created
{
  "dispute_id": 1,
  "status": "open",
  "submitted_at": "2026-04-23T10:00:00.000Z",
  "transaction_chain": {
    "id": 1,
    "dispute_id": 1,
    "chain_data": [ /* your submitted hops */ ],
    "created_at": "2026-04-23T10:00:00.000Z"
  }
}

Status Codes

201 Created 400 Validation error 500 Server error
GET /api/disputes List disputes

Returns paginated disputes with agent metadata. Supports filtering by status, agent, and date range. Max 100 results per page.

Query Parameters

ParameterTypeRequiredDescription
status string optional Filter by dispute status. One of: open, investigating, resolved, escalated.
agent_id integer optional Filter by agent (matches either submitter or fault agent).
from string optional Start of date range. ISO 8601 (e.g. 2026-04-01).
to string optional End of date range. ISO 8601.
page integer optional Page number, 1-indexed. Default: 1.
limit integer optional Results per page. Default: 20. Max: 100.

Example

curl
curl "https://arbiter-2.polsia.app/api/disputes?status=open&limit=50" \
  -H "Authorization: Bearer arb_live_..."

Response

200 OK
{
  "disputes": [
    {
      "id": 1,
      "status": "open",
      "description": "Agent C delivered corrupt data payload",
      "submitter_agent_id": 42,
      "submitter_agent_name": "BuyerBot",
      "submitter_external_id": "agent-buyer-001",
      "fault_agent_id": null,
      "fault_agent_name": null,
      "submitted_at": "2026-04-23T10:00:00.000Z",
      "updated_at": "2026-04-23T10:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 1,
    "total_pages": 1
  }
}

Status Codes

200 OK 400 Invalid filter value 500 Server error
GET /api/disputes/:id Get dispute details

Returns the full dispute record including agent metadata, the transaction chain, and any resolutions.

Path Parameters

ParameterTypeDescription
id integer Dispute ID returned from POST /api/disputes.

Example

curl
curl https://arbiter-2.polsia.app/api/disputes/1 \
  -H "Authorization: Bearer arb_live_..."

Response

200 OK
{
  "id": 1,
  "status": "resolved",
  "description": "Agent C delivered corrupt data payload",
  "submitter_agent_id": 42,
  "submitter_agent_name": "BuyerBot",
  "submitter_external_id": "agent-buyer-001",
  "submitter_platform": "sapiom",
  "fault_agent_id": 44,
  "fault_agent_name": "DataBot",
  "fault_external_id": "agent-data-003",
  "fault_platform": "sapiom",
  "submitted_at": "2026-04-23T10:00:00.000Z",
  "updated_at": "2026-04-23T10:00:05.000Z",
  "transaction_chains": [
    {
      "id": 1,
      "dispute_id": 1,
      "chain_data": [ /* hops */ ],
      "created_at": "2026-04-23T10:00:00.000Z"
    }
  ],
  "resolutions": [
    {
      "id": 1,
      "dispute_id": 1,
      "action": "full_refund",
      "fault_agent_id": 44,
      "reasoning": "Agent C failed to deliver required output",
      "created_at": "2026-04-23T10:00:05.000Z"
    }
  ]
}

Status Codes

200 OK 400 Invalid ID format 404 Dispute not found 500 Server error
GET /api/disputes/:id/resolution Get dispute resolution

Returns the resolution(s) for a dispute. Returns 404 if no resolution exists yet — the dispute is still being processed. Poll this endpoint after submitting a dispute to check for completion.

Path Parameters

ParameterTypeDescription
id integer Dispute ID.

Resolution Actions

ActionMeaning
full_refund Fault agent owes 100% of transaction value to submitting agent.
partial_credit Partial value returned. See resolution.metadata for amount.
escalation Dispute could not be resolved algorithmically. Requires human review.
no_fault Chain analysis found no clear fault. No action taken.

Example

curl
curl https://arbiter-2.polsia.app/api/disputes/1/resolution \
  -H "Authorization: Bearer arb_live_..."

Response

200 OK
{
  "dispute_id": 1,
  "dispute_status": "resolved",
  "resolutions": [
    {
      "id": 1,
      "dispute_id": 1,
      "action": "full_refund",
      "fault_agent_id": 44,
      "reasoning": "Agent C failed to deliver required output",
      "metadata": {},
      "created_at": "2026-04-23T10:00:05.000Z"
    }
  ]
}

Not Yet Resolved (404)

404 Not Found
{
  "error": "No resolution found for this dispute",
  "dispute_id": 1,
  "dispute_status": "investigating"
}

Status Codes

200 Resolution found 404 No resolution yet or dispute not found 500 Server error
POST /api/settlements Execute a Stripe settlement

Execute a Stripe payment settlement for a resolved dispute. Requires STRIPE_SECRET_KEY configured on the server. Supports three settlement types: refund (buyer wins), charge (seller wins), and split (shared fault). All amounts are in cents.

Request Body

ParameterTypeRequiredDescription
dispute_id integer Arbiter dispute ID. Must be resolved.
amount_cents integer Settlement amount in cents (min: 1).
settlement_type string One of: refund, charge, split.
stripe_payment_intent_id string For refund/split Stripe payment intent ID from the original transaction.
fault_agent_id integer Optional Arbiter agent ID of the party at fault.
fault_share_cents integer For split Fault agent's payment share (cents). Used in split settlements.
buyer_share_cents integer For split Buyer's refund share (cents). Used in split settlements.
idempotency_key string Optional Unique key to prevent duplicate settlements. Re-submitting the same key for the same dispute returns the existing settlement.

Example: Refund (buyer wins)

Request
curl -X POST https://arbiter-2.polsia.app/api/settlements \\
  -H \"Authorization: Bearer arb_live_...\" \\
  -H \"Content-Type: application/json\" \\
  -d '{
    \"dispute_id\": 42,
    \"amount_cents\": 5000,
    \"settlement_type\": \"refund\",
    \"stripe_payment_intent_id\": \"pi_xxx\",
    \"idempotency_key\": \"dispute-42-full-refund\"
  }'

Response

201 Created
{
  \"id\": 1,
  \"dispute_id\": 42,
  \"settlement_type\": \"refund\",
  \"status\": \"succeeded\",
  \"amount_cents\": 5000,
  \"stripe_payment_intent_id\": \"pi_xxx\",
  \"stripe_refund_id\": \"re_xxx\",
  \"settled_at\": \"2026-04-29T12:30:00.000Z\",
  \"created_at\": \"2026-04-29T12:30:00.000Z\"
}

Status Codes

201 Settlement executed 400 Validation error or unresolved dispute 404 Dispute not found 502 Stripe API error (check stripe_error in response) 503 Stripe not configured
GET /api/settlements List settlements

List all settlements with optional filtering by dispute or status.

Query Parameters

ParameterTypeDescription
dispute_id integer Filter by dispute ID.
status string Filter by status: pending, succeeded, failed, cancelled.
page integer Page number. Default: 1.
limit integer Results per page. Default: 50. Max: 100.

Example

Request
curl https://arbiter-2.polsia.app/api/settlements?dispute_id=42 \\
  -H \"Authorization: Bearer arb_live_...\"

Response

200 OK
{
  \"settlements\": [
    {
      \"id\": 1,
      \"dispute_id\": 42,
      \"settlement_type\": \"refund\",
      \"status\": \"succeeded\",
      \"amount_cents\": 5000,
      \"stripe_refund_id\": \"re_xxx\"
    }
  ],
  \"pagination\": {
    \"page\": 1,
    \"limit\": 50,
    \"total\": 1,
    \"total_pages\": 1
  }
}
GET /api/settlements/:id Get settlement details

Returns a single settlement by ID including Stripe transaction details.

Path Parameters

ParameterTypeDescription
id integer Settlement ID returned from POST /api/settlements.

Response

200 OK
{
  \"id\": 1,
  \"dispute_id\": 42,
  \"settlement_type\": \"refund\",
  \"status\": \"succeeded\",
  \"amount_cents\": 5000,
  \"stripe_payment_intent_id\": \"pi_xxx\",
  \"stripe_refund_id\": \"re_xxx\",
  \"fault_agent_id\": 44,
  \"settled_at\": \"2026-04-29T12:30:00.000Z\",
  \"created_at\": \"2026-04-29T12:30:00.000Z\"
}

Status Codes

200 Settlement found 404 Settlement not found

Error Codes

All errors return JSON with an error string. HTTP status codes follow standard semantics.

Status Error Cause
400 Missing required fields: ... One or more required fields omitted from the request body.
400 chain_data must be an array chain_data was sent as a non-array value.
400 chain_data[n] must include agent_id, action, and timestamp A hop in the chain is missing a required field.
400 submitter_agent_id N not found The referenced agent has not been registered. Call POST /api/agents first.
400 Invalid status. Must be one of: ... Unknown dispute status passed to the filter.
400 Invalid "from" date format Date string could not be parsed. Use ISO 8601.
400 Invalid input type. A field received the wrong type (e.g. string instead of integer for an ID).
404 Dispute not found No dispute exists with the given ID.
404 No resolution found for this dispute Dispute exists but resolution is not yet available. Poll again.
409 Agent with this external_agent_id already exists Duplicate agent registration. Use the returned agent_id.
409 Duplicate entry. Resource already exists. Unique constraint violation on another field.
500 Internal server error Unexpected server error. Retry with exponential backoff.

Rate Limits

100
requests / minute
5,000
requests / day
20
disputes / minute

Rate limit headers are included in every response:

response headers
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1745510460

When you exceed the limit, Arbiter returns 429 Too Many Requests. Back off and retry after the timestamp in X-RateLimit-Reset.

Need higher limits for high-throughput agent platforms? Contact us — enterprise limits are available.

JavaScript / TypeScript SDK

A typed SDK is available for Node.js and TypeScript. Wraps all API endpoints with typed request/response objects.

Install

bash
npm install arbiter-client

Usage

typescript
import { ArbiterClient } from 'arbiter-client';

const arbiter = new ArbiterClient({
  apiKey: 'arb_live_your_key_here',
  baseUrl: 'https://arbiter-2.polsia.app' // optional, defaults to production
});

// Register an agent
const agent = await arbiter.registerAgent({
  external_agent_id: 'my-agent-001',
  name: 'MyBot',
  platform: 'sapiom'
});

// Submit a dispute
const dispute = await arbiter.submitDispute([
  { agent_id: 'my-agent-001', action: 'initiated_purchase', timestamp: '2026-04-23T10:00:00Z' },
  { agent_id: 'their-agent-002', action: 'failed_delivery', timestamp: '2026-04-23T10:01:00Z', outcome: 'failed' }
]);

// Poll for resolution
const resolution = await arbiter.getResolution(dispute.dispute_id);

The SDK source is available in the /sdk directory of the Arbiter repository.