Internal Beta · No API Key Yet

Conditional settlement.
Zero custody.

Payments release against a condition the protocol can verify, not against the other side’s word. Assets lock on-chain until it clears. You never hold a key, and never stand as the counterparty.

try it
$ curl http://localhost:8080/api/v1/offers?side=sell&asset=USDT
v1 covers OTC settlement · conditional transfers follow · call from your server, not the browser
Call from
JSPyGoRsRbPh$_
53
REST endpoints
4
Domains
2
Token grades
0
Keys we hold
Atara Payment Protocol

Your Backend's
Settlement Rail.

Plain HTTP. Predictable JSON. One surface covering accounts and on-chain allowances, an order book whose sell side is really locked, escrowed settlement tickets, and withdrawals you sign yourself.

  • REST + JSON · every account is an on-chain address
  • One-time confirmation token on anything that moves funds
  • Errors carry a remedy — a value you can resubmit as-is
  • phase is computed per observer — no client-side state machine
  • No SDK required — fetch / axios / requests / curl
settle.ts
// 1 — take a maker's offer
const r = await fetch(
  'http://localhost:8080/api/v1/offers/p1/take',
  { method: 'POST',
    headers: { 'X-Atara-User': 'demo' },
    body: JSON.stringify({
      amount: '73100', amount_kind: 'fiat'
    })
  }
);

// 2 — read the ticket
const order = await r.json();
{
  ref: 'ATR-8F42C1',
  state: 'match',
  phase: 'lock', actor: 'auto',
  amount: { amount: '10000', asset: 'USDT' },
  seconds_left: 20
}
Integration Patterns

How developers
ship with this.

Base URL
http://localhost:8080/api/v1

Every path on this page appends to this base.

Identity
X-Atara-User: <handle | address>

Mock auth during internal testing; omitted falls back to demo. Real auth lands before public release.

Moving Money
X-Atara-Confirmation: <token>

Only on calls that move or commit funds. Minted from POST /passkey/assert. 120 s, single use, bound to that exact amount and peer.

Endpoint Coverage

53 endpoints across 4 domains. Every one of them settles the same way: escrow on-chain, release on evidence.

53
Endpoints
4 domains
2
Token grades
signature moves · commit promises
6
Order states
match → s1 → s3 → s3v → s4 → s5
0
Fiat touched
bank-to-bank, outside the protocol
Assets

Digital assets only — GET /wallet never lists a fiat balance.

Fiat corridors

The fiat leg settles bank-to-bank between the two parties.

Also available

Conditional transfers run a separate state machine and sit outside the v1 contract.

Settlement Engine

Evidence Releases.
Not the Other Side.

After the fiat leg, the payer submits a bank receipt and the ticket sits in s3v until the party who received the fiat verifies it. The submitter can't verify their own receipt.

  • Sell offers lock coins on post — lock_tx is returned
  • Self-verify is refused with NOT_YOUR_CALL
  • A failed check moves to disputed, funds stay locked
  • Contract, tx hash and confirmations exposed for independent checks
  • A match timeout is cancelled, not expired — fill rate untouched
200 OK · order.json
{
  "ref": "ATR-8F42C1",
  "state": "s3v", "terminal": "",
  // computed for whoever is asking
  "phase": "verify", "actor": "you",
  "amount": { "amount": "10000", "asset": "USDT" },
  "otc": {
    "side": "sell", "unit_price": "7.31",
    "fiat_code": "CNY", "fiat_amount": "73100",
    "receipt_ref": "rcpt_7f2a"
  },
  "escrow": {
    "contract": "TEscrow...", "network": "TRON",
    "tx_hash": "0x...",
    "confirmations": 12, "required": 12
  },
  "state_deadline": "2026-09-02T07:44:11Z",
  "seconds_left": 6
}
Confirmation Tokens

Two Grades
of Yes.

Every outflow needs an explicit confirmation — no small-amount exemption. A token is a hash of this operation: change the amount or the counterparty and it no longer applies, and is voided on the spot.

  • signature — moves money. Sell offers, withdrawals, allowances
  • commit — promises only. Buy offers, taking a trade, declaring a transfer
  • Signature satisfies a commit endpoint. The reverse returns SIGNATURE_REQUIRED
  • 120 seconds, single use, persisted across restarts
  • An agent can commit to a trade without being able to sign money away
POST /passkey/assert
// request — bind the token to this exact payment
{
  "scope": "withdraw",
  "parts": ["payee-id", "USDT", "250.5"],
  "grade": "signature"
}

// response
{
  "confirmation": "a1b2c3…",
  "expires_at":   "2026-09-02T05:44:05Z",
  "grade":        "signature",
  "header":       "X-Atara-Confirmation"
}

// then pass it on the call that moves funds
curl -X POST .../withdrawals \
  -H "X-Atara-Confirmation: a1b2c3…"
Endpoint Catalog

Click to expand
— see the full request.

Amounts are decimal strings in the major unit. Times are RFC 3339 UTC. Use state_deadline for logic, seconds_left only for countdowns.

Error Format

Failures that tell you what to send.

One envelope for every failure. Branch on code, never on message. When the protocol can already tell a request will fail downstream, it stops it here and attaches a remedy.

422 · below_min_lot
{
  "error": {
    "code":    "BELOW_MIN_LOT",
    "field":   "amount",
    "message": "3000 CNY is below the maker's smallest lot",
    "remedy": {
      "action": "set_amount",
      "value":  "5000",
      "label":  "Use the smallest lot — 5000 CNY"
    }
  }
}
CONFIRMATION_INVALID— expired, used, or bound to a different payment
SIGNATURE_REQUIRED— needs a signature token, you sent commit
NOT_YOUR_CALL— receipt submitter tried to verify their own receipt
BELOW_MIN_LOT— under the maker's smallest lot · carries a remedy
ABOVE_AVAILABLE_QTY— over remaining, or lost a concurrent take · carries a remedy
NO_MATCH_WITH_COUNTERPARTY— that maker can't fill this, and we don't fall back
CAP_ABOVE_WINDOW— per-payment cap exceeds the window cap
KYC_NOT_APPROVED— listing config submitted before identity approval
Scope

When NOT to use this API.

Atara is a settlement protocol, not a venue and not a custodian. Two invariants shape everything above.

Holding or moving fiat

The fiat leg settles bank-to-bank between the parties. GET /wallet never lists a fiat asset, and a fiat withdrawal returns ASSET_REQUIRED.

Custody or key management

custody is always "self". External wallets grant allowances by on-chain approve; we can't sign for them, so we watch the chain instead.

Millisecond execution

Not a matching engine. Windows are measured in minutes and hours, and the fiat leg runs at bank speed.

Conditional transfers, in v1

POST /orders and its evidence and confirm routes exist and run, but sit outside the v1 contract. Specified with v2.

Internal-beta limitationsthese close before public release
❌ Real auth — identity is a header
❌ API keys and per-key quotas
⚠️ POST /offers doesn't check maker approval
⚠️ Timings default to demo speed
⚠️ Catalog usd_rate is a compile-time constant
⚠️ Agent assessment is a simulated layer
✅ Full order lifecycle, both directions
✅ Confirmation tokens, both grades
Timing windows

ATARA_DEMO_TIMING switches between two sets. Demo is the default: a 4-hour payment window runs 24 seconds, a 72-hour dispute window runs 15. Don't build countdowns against the demo numbers.