caput.dev configure your bot →

Invitation Format

The invitation is the data structure a seller's bot generates and shares with a prospective buyer. The buyer's wallet (or a manual review tool) reads it, the buyer signs the deploy bundle, and the contract goes live.

This document describes the invitation's JSON schema. Sophisticated buyers who want to verify an invitation independently of the bot's UI can read the JSON directly.

Note: this format will be finalized in Phase 4 of the build. The Phase 0 version below is the design intent; field names and exact structure may shift slightly as the spike validates the mechanics.

Top-level structure

{
  "version": "1",
  "option_id": "0x77a2…1c4f",
  "kind": "put",
  "seller": {
    "wallet": "rN7n3Eq8kQpExampleAddressHere",
    "deposit_asset": "XRP",
    "deposit_amount": "1.000000"
  },
  "terms": {
    "tenor_days": 15,
    "premium_pct": 3,
    "min_buyer_margin_pct": 10
  },
  "amm": {
    "pair": "XRP/RLUSD",
    "rate_at_creation": "0.5421",
    "max_slippage_pct": 2
  },
  "expires_at": "2026-04-29T00:00:00Z",
  "signature": "ed25519:abc123…def456"
}

Field-by-field

version

String. The invitation schema version. Currently "1". Future versions may change the schema; bots reject invitations with unknown versions.

option_id

Hex string. A unique identifier for this contract, generated by the seller's bot when the invitation is created. Used to:

kind

String, one of "put" or "call". The contract type from the buyer's perspective:

seller

Object describing the seller's deposit:

terms

Object describing contract terms:

These three fields are enum-restricted. Bots reject invitations with values outside these enums.

amm

Object describing the AMM venue:

expires_at

ISO 8601 timestamp. The invitation expires at this time. After expiry, no buyer can accept it. The seller can re-issue a fresh invitation at any time.

Default expiry is 24 hours from creation, but sellers can set shorter or longer windows.

signature

Cryptographic signature over the rest of the invitation, signed by the seller's wallet. Format: ed25519:<hex>.

The buyer's bot verifies:

How the buyer's bot uses an invitation

  1. Receive the invitation (paste, link, QR scan).
  2. Parse JSON, check schema version.
  3. Verify signature against seller's stated wallet.
  4. Check expiry is in the future.
  5. Check option_id against on-chain revocation memos to see if the seller revoked.
  6. Query the AMM for current rate; compare to rate_at_creation. If deviation exceeds max_slippage_pct, reject.
  7. Display terms to the buyer in the UI.
  8. Buyer picks their margin from the allowed enum values (must be ≥ min_buyer_margin_pct).
  9. Buyer signs the deploy bundle.

What the invitation does NOT contain

Verification independent of the bot

A sophisticated buyer who wants to verify an invitation without trusting their bot's UI can:

  1. Parse the JSON manually.
  2. Verify the signature using a standalone XRPL signing library (xrpl.js, xrpl-py, etc.).
  3. Compare the seller's wallet against the seller's public identity (their stated XRPL address on a website, in a forum post, wherever the seller publishes).
  4. Query the AMM rate manually via amm_info RPC against a public XRPL node.
  5. Check on-chain transactions for option_id revocation memos.

This is the audit-friendly path. The bot's UI is convenience; the JSON and the chain are truth.

Revocation

A seller can revoke an unaccepted invitation by submitting a transaction from their wallet with a memo of the form:

{
  "type": "revoke",
  "option_id": "0x77a2…1c4f"
}

Memo format: hex-encoded JSON in the transaction's Memos field, with MemoType set to caput-revoke.

Buyer bots check for revocation memos before allowing acceptance. Revoked invitations cannot be deployed, even if the buyer has the original JSON.

Future versions

Schema changes will increment the version field. The bot's invitation parser is version-aware and rejects unknown versions. Backward compatibility for old versions will be maintained for at least one major release.