{
  "openapi": "3.1.0",
  "info": {
    "title": "Route public testnet API",
    "version": "0.10.7-preview",
    "description": "Hosted CCTP Ethereum Sepolia to Stellar testnet. Explicit Route-Network: testnet is required. Route prepares, verifies wallet signatures, submits once and verifies receipts. Managed Stellar minting through OpenZeppelin Channels includes background tracking; customer-funded minting remains client-driven; reverse direction and other testnet pairs are unavailable. See testnet-api.md. Keys select a named policy. New policies enforce TEST_USDC amount and protocol-fee limits; USD prices and complete arrival rankings are not evaluated. GET /payments/{id}/next-action supplies a normalized observational action snapshot; see /docs/next-actions.md. Existing mutation endpoints and their authorization requirements are unchanged.",
    "x-documentation-revision": "2026-10-05",
    "x-integration-changelog": "/docs/changelog.md"
  },
  "servers": [
    {
      "url": "https://route.click/v1",
      "description": "Hosted Route API; send Route-Network: testnet."
    },
    {
      "url": "http://localhost:8788/v1",
      "description": "Local development; requires TESTNET_EXECUTION_ENABLED=true for signed submission."
    }
  ],
  "security": [
    {
      "RouteKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "RouteKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "rt_test_<secret>",
        "description": "Use a key for the selected Route-Network. Mismatches return 403 KEY_NETWORK_MISMATCH. Legacy rt_sandbox_ keys retain their original access and restrictions."
      }
    },
    "schemas": {
      "Candidate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "circle:standard",
              "circle:fast"
            ]
          },
          "adapter": {
            "type": "string",
            "const": "circle"
          },
          "route": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "quoted",
              "unavailable"
            ]
          },
          "received": {
            "type": [
              "string",
              "null"
            ]
          },
          "minimumReceived": {
            "type": "null"
          },
          "fees": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "label": {
                  "type": "string"
                },
                "amount": {
                  "type": "string",
                  "pattern": "^\\d+(\\.\\d+)?$"
                },
                "currency": {
                  "type": "string"
                },
                "treatment": {
                  "type": "string",
                  "enum": [
                    "deducted",
                    "additional",
                    "included"
                  ]
                }
              },
              "required": [
                "label",
                "amount",
                "currency",
                "treatment"
              ]
            }
          },
          "eta": {
            "type": "object",
            "properties": {
              "seconds": {
                "type": "null"
              },
              "scope": {
                "type": "string"
              },
              "stage": {
                "type": "string",
                "const": "end-to-end"
              }
            },
            "required": [
              "seconds",
              "scope",
              "stage"
            ]
          },
          "costComplete": {
            "type": "boolean",
            "const": false
          },
          "estimatedCostUsd": {
            "type": "null"
          },
          "unknowns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "capacity": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string"
              },
              "scope": {
                "type": "string"
              }
            },
            "required": [
              "status",
              "scope"
            ]
          },
          "limits": {
            "type": "object",
            "properties": {
              "minimumAmount": {
                "type": "string"
              },
              "maximumAmount": {
                "type": "string"
              }
            },
            "required": [
              "minimumAmount",
              "maximumAmount"
            ]
          },
          "checks": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "decision": {
            "type": "string",
            "enum": [
              "needs-data",
              "excluded"
            ]
          },
          "observedAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "adapter",
          "route",
          "status",
          "received",
          "minimumReceived",
          "fees",
          "eta",
          "costComplete",
          "estimatedCostUsd",
          "unknowns",
          "capacity",
          "limits",
          "checks",
          "decision",
          "observedAt",
          "expiresAt"
        ],
        "description": "Testnet candidate. Both views preserve required limits, checks, outputs, scoped ETA and expiry; compact omits optional provider diagnostic evidence."
      },
      "Action": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "approval",
              "burn",
              "mint"
            ]
          },
          "family": {
            "type": "string",
            "enum": [
              "evm",
              "stellar"
            ]
          },
          "network": {
            "type": "string",
            "enum": [
              "ethereum-sepolia",
              "stellar-testnet"
            ]
          },
          "sender": {
            "type": "string"
          },
          "nonce": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "New CCTP burns and customer-signed mints: five-minute action review; token approvals: 15 minutes. Honor the saved deadline; fresh fee and transaction checks still apply."
          },
          "expired": {
            "type": "boolean"
          },
          "fee": {
            "type": "string",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "feeCurrency": {
            "type": "string",
            "enum": [
              "wei",
              "stroop"
            ]
          },
          "transaction": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "chainId": {
                    "type": "string"
                  },
                  "from": {
                    "type": "string"
                  },
                  "to": {
                    "type": "string"
                  },
                  "data": {
                    "type": "string"
                  },
                  "value": {
                    "type": "string"
                  },
                  "nonce": {
                    "type": "string"
                  },
                  "gas": {
                    "type": "string"
                  },
                  "gasPrice": {
                    "type": "string"
                  }
                },
                "required": [
                  "chainId",
                  "from",
                  "to",
                  "data",
                  "value",
                  "nonce",
                  "gas",
                  "gasPrice"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "xdr": {
                    "type": "string"
                  },
                  "hash": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{64}$"
                  },
                  "networkPassphrase": {
                    "type": "string",
                    "const": "Test SDF Network ; September 2015"
                  }
                },
                "required": [
                  "xdr",
                  "hash",
                  "networkPassphrase"
                ]
              }
            ]
          },
          "transactionHash": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "awaiting_signature",
              "submitted",
              "confirmed",
              "failed",
              "abandoned"
            ]
          }
        },
        "required": [
          "id",
          "kind",
          "family",
          "network",
          "sender",
          "nonce",
          "expiresAt",
          "expired",
          "fee",
          "feeCurrency",
          "transaction",
          "transactionHash",
          "status"
        ]
      },
      "Quote": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "quote"
          },
          "network": {
            "type": "string",
            "const": "testnet"
          },
          "apiVersion": {
            "type": "string",
            "const": "v1"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "input": {
            "type": "object",
            "properties": {
              "sourceAssetId": {
                "type": "string"
              },
              "destinationAssetId": {
                "type": "string"
              },
              "amount": {
                "type": "string",
                "pattern": "^\\d+(\\.\\d+)?$"
              },
              "source": {
                "type": "string"
              },
              "destination": {
                "type": "string"
              },
              "sourceAsset": {
                "type": "object"
              },
              "destinationAsset": {
                "type": "object"
              }
            },
            "required": [
              "sourceAssetId",
              "destinationAssetId",
              "amount",
              "source",
              "destination",
              "sourceAsset",
              "destinationAsset"
            ],
            "description": "Exact requested catalog IDs, decimal quantity in source asset units, networks and optional slippage. Mainnet compact responses omit the repeated resolved sourceAsset and destinationAsset objects; obtain their identities from GET /assets or view=full. Testnet retains its required resolved asset fields."
          },
          "candidates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Candidate"
            }
          },
          "selected": {
            "type": "null",
            "description": "Always null for this testnet comparison. Explicitly choose an available candidate whose decision is not excluded; this is not a cheapest or fastest recommendation."
          },
          "decision": {
            "type": "string"
          },
          "policyEvaluation": {
            "type": "string",
            "const": "testnet-unvalued"
          },
          "policyVersion": {
            "type": "integer"
          },
          "connectionVersion": {
            "type": "integer"
          },
          "observedAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "expired": {
            "type": "boolean"
          },
          "executionEnabled": {
            "type": "boolean"
          },
          "policyId": {
            "type": "string",
            "format": "uuid"
          },
          "policyName": {
            "type": "string",
            "description": "Optional diagnostic metadata returned with view=full."
          },
          "policy": {
            "type": "object",
            "description": "Optional diagnostic metadata returned with view=full."
          }
        },
        "required": [
          "object",
          "network",
          "apiVersion",
          "id",
          "projectId",
          "input",
          "candidates",
          "selected",
          "decision",
          "policyEvaluation",
          "policyVersion",
          "connectionVersion",
          "observedAt",
          "expiresAt",
          "expired",
          "executionEnabled"
        ],
        "description": "Saved quote observation returned by compact (testnet default) or full. Testnet has no automatic recommendation; payment creation requires an explicit candidate. Neither view authorizes spending; expiry and fresh wallet checks still apply."
      },
      "Payment": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "payment"
          },
          "network": {
            "type": "string",
            "const": "testnet"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "quoteId": {
            "type": "string",
            "format": "uuid"
          },
          "candidateId": {
            "type": "string"
          },
          "version": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "awaiting_action",
              "source_pending",
              "approval_confirmed",
              "source_reverted",
              "attesting",
              "awaiting_destination",
              "destination_pending",
              "destination_failed",
              "completed",
              "cancelled"
            ]
          },
          "paymentState": {
            "$ref": "#/components/schemas/PaymentState"
          },
          "executionEnabled": {
            "type": "boolean"
          },
          "intent": {
            "type": [
              "object",
              "null"
            ]
          },
          "tracking": {
            "type": "object",
            "description": "Verified receipt evidence and observed delivery state. No completed claim until the exact mint receipt is verified."
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Action"
            }
          },
          "events": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "version": {
                  "type": "integer"
                },
                "kind": {
                  "type": "string"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              },
              "required": [
                "id",
                "version",
                "kind",
                "created_at"
              ]
            }
          },
          "nextAction": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Action"
              },
              {
                "type": "null"
              }
            ]
          },
          "nextStep": {
            "type": "string",
            "enum": [
              "prepare",
              "sign-and-submit-in-wallet",
              "refresh",
              "none",
              "prepare-transaction",
              "execute",
              "confirm-wallet-broadcast",
              "review-required",
              "renew-mint",
              "renew-source"
            ],
            "description": "Testnet-only hint. nextAction is an action object, not the mainnet string. Unknown future states pause signing/submission."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "transaction": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Transaction"
              },
              {
                "type": "null"
              }
            ]
          },
          "destinationExecution": {
            "type": [
              "object",
              "null"
            ],
            "description": "Managed Circle-to-Stellar delivery. A relay submission is not proof of settlement. `failed` (Channels reported the relay failed or expired, or replaced it more than 16 times) and `submission-unknown` (no saved Channels relay ID, so Route cannot poll the attempt) require review. `lastError` holds the saved relay evidence. When `lastError.retryAllowed` is true, Route re-mints the same saved call once automatically after `lastError.remintAfter`, only while the CCTP nonce is unused at a fresh Stellar ledger and the call still simulates without new authorization; there is no second automatic re-mint. A message minted by a relay Route did not record stays in review with `lastError.code` `DESTINATION_MINTED_UNRECORDED`.",
            "properties": {
              "mode": {
                "const": "managed"
              },
              "provider": {
                "const": "openzeppelin-channels"
              },
              "state": {
                "type": "string",
                "enum": [
                  "waiting-for-source",
                  "paused",
                  "submitting",
                  "submitted",
                  "submission-unknown",
                  "failed",
                  "completed",
                  "cancelled"
                ]
              },
              "transactionHash": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Latest relay hash reported by Channels for the current relay attempt; tracking verifies this hash."
              },
              "relayHashes": {
                "type": "array",
                "items": {
                  "type": "string",
                  "pattern": "^[a-f0-9]{64}$"
                },
                "description": "Present only after Channels resubmitted the relay under a new hash: every reported hash, oldest (the first saved hash) first. Route verifies the latest one."
              },
              "relayAttempts": {
                "type": "array",
                "maxItems": 1,
                "items": {
                  "type": "object",
                  "properties": {
                    "attempt": {
                      "type": "integer"
                    },
                    "transactionId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "relayHashes": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "pattern": "^[a-f0-9]{64}$"
                      }
                    },
                    "state": {
                      "type": "string",
                      "enum": [
                        "submission-unknown",
                        "failed"
                      ]
                    },
                    "lastError": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "attemptedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "remintedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  }
                },
                "description": "Present only after Route's single automatic re-mint: the earlier relay attempt it replaced, with its Channels relay ID, every hash Channels reported, its state and saved evidence. Completion follows whichever recorded relay minted the message."
              },
              "customerSignatureRequired": {
                "const": false
              },
              "customerFee": {
                "type": "object",
                "properties": {
                  "amount": {
                    "const": "0"
                  },
                  "currency": {
                    "const": "XLM"
                  }
                }
              },
              "lastError": {
                "type": [
                  "object",
                  "null"
                ]
              }
            },
            "additionalProperties": true
          }
        },
        "required": [
          "object",
          "network",
          "id",
          "projectId",
          "quoteId",
          "candidateId",
          "version",
          "status",
          "paymentState",
          "executionEnabled",
          "intent",
          "tracking",
          "actions",
          "events",
          "nextAction",
          "nextStep",
          "createdAt",
          "updatedAt"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "object",
                "description": "Optional safe recovery fields; branch on error.code. 409 WALLET_TRANSACTION_REVIEW_REQUIRED supplies WalletAlteredTransaction evidence."
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "PreparedAction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "approval",
              "burn",
              "mint"
            ]
          },
          "family": {
            "type": "string",
            "enum": [
              "evm",
              "stellar"
            ]
          },
          "network": {
            "type": "string",
            "enum": [
              "ethereum-sepolia",
              "stellar-testnet"
            ]
          },
          "sender": {
            "type": "string"
          },
          "nonce": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "New CCTP burns and customer-signed mints: five-minute action review; token approvals: 15 minutes. Honor the saved deadline; fresh fee and transaction checks still apply."
          },
          "expired": {
            "type": "boolean"
          },
          "fee": {
            "type": "string",
            "pattern": "^\\d+(\\.\\d+)?$"
          },
          "feeCurrency": {
            "type": "string",
            "enum": [
              "wei",
              "stroop"
            ]
          },
          "transaction": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "chainId": {
                    "type": "string"
                  },
                  "from": {
                    "type": "string"
                  },
                  "to": {
                    "type": "string"
                  },
                  "data": {
                    "type": "string"
                  },
                  "value": {
                    "type": "string"
                  },
                  "nonce": {
                    "type": "string"
                  },
                  "gas": {
                    "type": "string"
                  },
                  "gasPrice": {
                    "type": "string"
                  }
                },
                "required": [
                  "chainId",
                  "from",
                  "to",
                  "data",
                  "value",
                  "nonce",
                  "gas",
                  "gasPrice"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "xdr": {
                    "type": "string"
                  },
                  "hash": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{64}$"
                  },
                  "networkPassphrase": {
                    "type": "string",
                    "const": "Test SDF Network ; September 2015"
                  }
                },
                "required": [
                  "xdr",
                  "hash",
                  "networkPassphrase"
                ]
              }
            ]
          },
          "transactionHash": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "awaiting_signature",
              "submitted",
              "confirmed",
              "failed",
              "abandoned"
            ]
          }
        },
        "required": [
          "kind",
          "family",
          "network",
          "sender",
          "nonce",
          "expiresAt",
          "fee",
          "feeCurrency",
          "transaction"
        ]
      },
      "Transaction": {
        "type": "object",
        "required": [
          "object",
          "id",
          "network",
          "state",
          "transaction",
          "executionEnabled",
          "signingEnabled",
          "submissionEnabled",
          "sourceHash",
          "expired",
          "authorizationPrepared"
        ],
        "properties": {
          "object": {
            "const": "payment_transaction"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "network": {
            "enum": [
              "ethereum-sepolia",
              "stellar-testnet"
            ]
          },
          "state": {
            "enum": [
              "ready",
              "signed",
              "submitting",
              "submitted",
              "submission-unknown",
              "expired",
              "cancelled"
            ]
          },
          "transaction": {
            "$ref": "#/components/schemas/PreparedAction"
          },
          "executionEnabled": {
            "type": "boolean"
          },
          "signingEnabled": {
            "type": "boolean",
            "description": "Requires a persisted authorization, current review and enabled execution. Preparing an unsigned action alone does not enable signing."
          },
          "submissionEnabled": {
            "type": "boolean"
          },
          "sourceHash": {
            "type": [
              "string",
              "null"
            ]
          },
          "expired": {
            "type": "boolean"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "New CCTP burns and customer-signed mints: five-minute action review; token approvals: 15 minutes. Honor the saved deadline; fresh fee and transaction checks still apply."
          },
          "lastError": {
            "type": [
              "string",
              "object",
              "null"
            ],
            "description": "A string for submission outcomes. An object (WalletAlteredTransaction, code WALLET_TRANSACTION_REVIEW_REQUIRED) when the wallet altered the handed-off transaction; paymentState is then REQUIRES_ATTENTION and nextStep review-required. Route keeps that evidence as lastError: a later submission outcome is nested under it as submission."
          },
          "kind": {
            "enum": [
              "approval",
              "burn",
              "mint"
            ]
          },
          "sender": {
            "type": "string"
          },
          "sequence": {
            "type": "integer",
            "minimum": 1
          },
          "authorization": {
            "const": "transaction-signature"
          },
          "intentApprovalRequired": {
            "const": false
          },
          "authorizationPrepared": {
            "type": "boolean",
            "description": "True only after Route has persisted the signing authorization. A prepared action returned before POST /transaction has this false and cannot be signed through Route. signingEnabled also requires authorizationPrepared."
          },
          "walletBroadcastAvailable": {
            "type": "boolean",
            "description": "EVM-only alternative before saving a signature. POST /transaction/broadcast repeats current authorization checks. False once unresolved review evidence is recorded for a burn (or, for an approval too, the same payment found at another nonce or another reported transaction the wallet signed)."
          },
          "walletBroadcast": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/WalletBroadcast"
              },
              {
                "type": "null"
              }
            ]
          },
          "mintRenewalEnabled": {
            "type": "boolean",
            "description": "The current expired customer Stellar mint is eligible for a renewal proof. This flag does not authorize replacement or submission; POST /transaction/renew must still verify chain evidence."
          },
          "submissionStartedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Recorded Route submission attempt time. A missing value does not prove that a signed transaction was never broadcast elsewhere."
          }
        },
        "description": " Wallet handoffs awaiting a hash are projected as submission-unknown with signingEnabled and submissionEnabled false. Once verified, state is submitted; normal receipt tracking establishes finality and delivery."
      },
      "TransactionResult": {
        "type": "object",
        "required": [
          "transaction",
          "network"
        ],
        "properties": {
          "network": {
            "const": "testnet"
          },
          "transaction": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Transaction"
              },
              {
                "type": "null"
              }
            ]
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Transaction"
            }
          },
          "executionEnabled": {
            "type": "boolean"
          }
        }
      },
      "Policy": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "minimum": 0
          },
          "policy": {
            "type": "object"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "network": {
            "enum": [
              "mainnet",
              "testnet",
              "both"
            ]
          },
          "warnings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ArrivalWarning"
            },
            "description": "Arrival-evidence warnings for speed priority or a delivery deadline, derived when the policy is read or saved. Empty when neither is set and for test-token policies."
          }
        },
        "required": [
          "version",
          "policy"
        ]
      },
      "PolicyInput": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "minimum": 0
          },
          "valueCurrency": {
            "enum": [
              "TEST_USDC",
              "USD"
            ],
            "description": "TEST_USDC for a named Testnet policy. USD is accepted only for an existing shared legacy policy."
          },
          "priority": {
            "enum": [
              "cost",
              "speed"
            ]
          },
          "maxFee": {
            "type": "string"
          },
          "maxSeconds": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "maximum": 86400,
            "description": "Named Testnet policies require null. Arrival deadlines are unavailable."
          },
          "minAmount": {
            "type": "string"
          },
          "maxAmount": {
            "type": "string"
          },
          "providers": {
            "type": "array",
            "items": {
              "enum": [
                "circle",
                "allbridge",
                "near",
                "layerzero",
                "axelar"
              ],
              "description": "Named Testnet policies allow Circle only. Shared legacy policies retain their mainnet provider list."
            }
          }
        },
        "required": [
          "version",
          "valueCurrency",
          "priority",
          "maxFee",
          "maxSeconds",
          "minAmount",
          "maxAmount",
          "providers"
        ],
        "additionalProperties": false
      },
      "PaymentNextAction": {
        "type": "object",
        "required": [
          "object",
          "schemaVersion",
          "network",
          "paymentId",
          "activePaymentId",
          "flow",
          "adapter",
          "paymentVersion",
          "preparationVersion",
          "authorizationId",
          "observedAt",
          "status",
          "expiresAt",
          "action",
          "checks",
          "blockers",
          "tracking",
          "links",
          "notice"
        ],
        "properties": {
          "object": {
            "const": "payment_next_action"
          },
          "schemaVersion": {
            "type": "integer",
            "const": 1
          },
          "network": {
            "const": "testnet"
          },
          "paymentId": {
            "type": "string",
            "format": "uuid"
          },
          "activePaymentId": {
            "type": "string",
            "format": "uuid",
            "description": "For a composed workflow, the currently active child payment; otherwise paymentId."
          },
          "flow": {
            "type": "string",
            "enum": [
              "near",
              "protocol",
              "testnet",
              "composed"
            ]
          },
          "adapter": {
            "type": [
              "string",
              "null"
            ]
          },
          "paymentVersion": {
            "type": "integer",
            "minimum": 1
          },
          "preparationVersion": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "authorizationId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "observedAt": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "$ref": "#/components/schemas/PaymentState"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Current relevant review or quote deadline, when present. Expiry does not undo a broadcast or invalidate signed EVM bytes on-chain."
          },
          "action": {
            "$ref": "#/components/schemas/PaymentNextStep"
          },
          "checks": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Saved checks in their existing flow-specific shape. Empty does not establish fresh wallet or fee readiness."
          },
          "blockers": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Saved blockers in their existing flow-specific shape; action may still require review for expiry, unknown state or unavailable execution."
          },
          "tracking": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Saved flow-specific settlement evidence. No provider/chain refresh is performed by reading this projection."
          },
          "links": {
            "type": "object",
            "required": [
              "payment",
              "nextAction"
            ],
            "properties": {
              "payment": {
                "type": "string"
              },
              "nextAction": {
                "type": "string"
              }
            }
          },
          "notice": {
            "type": "string"
          }
        },
        "description": "Observational projection of the existing payment. Does not authorize a signature, reserve liquidity, retry an operation, or prove current chain state. Every mutation revalidates its own evidence. Preserve the existing payment on an uncertain outcome."
      },
      "PaymentNextStep": {
        "type": "object",
        "required": [
          "type",
          "actor",
          "message",
          "operation",
          "payload"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "prepare-payment",
              "request-intent-approval",
              "sign-intent",
              "prepare-transaction",
              "sign-transaction",
              "submit-transaction",
              "refresh-review",
              "track",
              "continue-leg",
              "advance",
              "reconcile",
              "completed",
              "refunded",
              "cancelled",
              "review-required",
              "confirm-wallet-broadcast",
              "renew-mint",
              "renew-approval",
              "close-payment",
              "renew-source"
            ],
            "description": "Unknown future action types must pause automatic signing and submission; update the integration before continuing."
          },
          "actor": {
            "type": "string",
            "enum": [
              "app",
              "wallet",
              "operator",
              "none"
            ],
            "description": "The party responsible for the next step. wallet requires separately authorized sign-only handling; operator requires review."
          },
          "message": {
            "type": "string"
          },
          "operation": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PaymentNextOperation"
              },
              {
                "type": "null"
              }
            ]
          },
          "payload": {
            "description": "Wallet review/signing payload only when applicable; otherwise null. Flow-specific challenge or unsigned transaction, not a private key or saved signed transaction. Preserve and independently review its exact contents."
          }
        }
      },
      "PaymentNextOperation": {
        "type": "object",
        "required": [
          "method",
          "path",
          "body",
          "idempotencyKeyRequired",
          "requiredInput"
        ],
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "GET",
              "POST"
            ]
          },
          "path": {
            "type": "string",
            "pattern": "^/v1/payments/",
            "description": "Origin-relative Route endpoint, including /v1. Use the trusted Route API origin; do not prepend /v1 a second time or follow arbitrary hosts."
          },
          "body": {
            "type": "object",
            "additionalProperties": true,
            "description": "Saved-state request fields such as the correct version or authorizationId. Supplement only the listed required inputs for this action; never overwrite these identities."
          },
          "idempotencyKeyRequired": {
            "type": "boolean",
            "description": "When true, persist a new UUID for this logical operation before the request. Reuse it and the identical body after a lost response. It does not grant authority to run the operation."
          },
          "requiredInput": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "uniqueItems": true,
            "description": "Missing caller inputs, such as paymentIntent, signature or signedTransaction. An empty list does not mean a signature or submission is preauthorized."
          }
        }
      },
      "RecoveryStage": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "network",
          "hash",
          "verified",
          "finalized",
          "includedAt"
        ],
        "properties": {
          "network": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "hash": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z0-9:_-]{1,128}$"
          },
          "verified": {
            "type": "boolean"
          },
          "finalized": {
            "type": "boolean"
          },
          "includedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "description": "Saved funding, delivery or refund evidence. A hash alone does not prove submission; verified and finalized are distinct."
      },
      "RecoveryReceipt": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "observed",
          "included",
          "successful",
          "finalized"
        ],
        "properties": {
          "observed": {
            "type": "boolean"
          },
          "included": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "successful": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "finalized": {
            "type": [
              "boolean",
              "null"
            ]
          }
        },
        "description": "Observed means this saved transaction view includes a receipt observation. Null flags mean unavailable evidence, not false. Separate verified tracking may exist even when this receipt is unobserved."
      },
      "RecoveryTransaction": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "kind",
          "network",
          "state",
          "hash",
          "submissionAttempted",
          "receipt",
          "expiresAt",
          "reviewExpired"
        ],
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "approval",
              "approval-reset",
              "burn",
              "transfer",
              "mint",
              "deposit",
              "unknown"
            ]
          },
          "network": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "state": {
            "type": "string",
            "enum": [
              "ready",
              "signed",
              "submitting",
              "submitted",
              "submission-unknown",
              "expired",
              "unknown",
              "cancelled"
            ]
          },
          "hash": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z0-9:_-]{1,128}$"
          },
          "submissionAttempted": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "receipt": {
            "$ref": "#/components/schemas/RecoveryReceipt"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "reviewExpired": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "submissionObservation": {
            "$ref": "#/components/schemas/StellarSubmissionObservation"
          },
          "sourceSubmissionObservation": {
            "$ref": "#/components/schemas/SourceSubmissionObservation"
          }
        },
        "description": "An allowlisted saved action summary. No unsigned payload, signing challenge, signature or signed transaction bytes are included. Testnet exposes its latest saved action; this is not a complete historical action ledger."
      },
      "RecoveryDiscrepancy": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "code",
          "network",
          "purpose",
          "transactionHash",
          "providerReportedAmountMinor",
          "observedRecipientAmountMinor",
          "differenceMinor",
          "minimumAmountMinor",
          "meetsMinimum",
          "finalized",
          "confirmations",
          "blockHeight",
          "blockHash"
        ],
        "properties": {
          "code": {
            "enum": [
              "BITCOIN_SETTLEMENT_AMOUNT_MISMATCH",
              "TRON_SETTLEMENT_AMOUNT_MISMATCH"
            ]
          },
          "network": {
            "enum": [
              "btc",
              "tron"
            ]
          },
          "purpose": {
            "type": "string",
            "enum": [
              "delivery",
              "refund"
            ]
          },
          "transactionHash": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z0-9:_-]{1,128}$"
          },
          "providerReportedAmountMinor": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^\\d{1,78}$"
          },
          "observedRecipientAmountMinor": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^\\d{1,78}$"
          },
          "differenceMinor": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^-?\\d{1,78}$"
          },
          "minimumAmountMinor": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^\\d{1,78}$"
          },
          "meetsMinimum": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "finalized": {
            "type": "boolean"
          },
          "confirmations": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "blockHeight": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "blockHash": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z0-9:_-]{1,128}$"
          }
        },
        "description": "BTC values are satoshis encoded as decimal strings. Meeting a minimum does not prove which payment owns a larger payout. Exact provider-to-chain attribution remains required.",
        "oneOf": [
          {
            "properties": {
              "code": {
                "const": "BITCOIN_SETTLEMENT_AMOUNT_MISMATCH"
              },
              "network": {
                "const": "btc"
              }
            }
          },
          {
            "properties": {
              "code": {
                "const": "TRON_SETTLEMENT_AMOUNT_MISMATCH"
              },
              "network": {
                "const": "tron"
              }
            }
          }
        ]
      },
      "RecoveryWalletReservation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "kind",
          "authorizationId",
          "network",
          "sender",
          "nonce",
          "transactionHash",
          "outputIndex"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "sequence",
              "bitcoin-input"
            ]
          },
          "authorizationId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "network": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "sender": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z0-9:_-]{1,128}$"
          },
          "nonce": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^\\d{1,78}$"
          },
          "transactionHash": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z0-9:_-]{1,128}$"
          },
          "outputIndex": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          }
        },
        "description": "Saved wallet sequence or reserved Bitcoin input; transactionHash/outputIndex identify a reserved input outpoint, not a completed payout."
      },
      "RecoveryApiLimitReservation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "apiKeyId",
          "preparationId",
          "amountUsd",
          "state",
          "reservedAt",
          "committedAt"
        ],
        "properties": {
          "apiKeyId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "preparationId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "amountUsd": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^\\d{1,78}(\\.\\d{1,42})?$"
          },
          "state": {
            "type": "string",
            "enum": [
              "reserved",
              "committed",
              "unknown",
              "released"
            ]
          },
          "reservedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "committedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "description": "API-key spending-limit accounting. apiKeyId is a public record identifier, never the secret key. A committed source amount is not proof of destination delivery."
      },
      "RecoveryCreditReservation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "paymentId",
          "credits",
          "state",
          "updatedAt"
        ],
        "properties": {
          "paymentId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "credits": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^\\d{1,78}$"
          },
          "state": {
            "type": "string",
            "enum": [
              "reserved",
              "charged",
              "released",
              "unknown"
            ]
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "description": "Route usage-credit accounting; separate from payment value and chain fees."
      },
      "RecoverySafety": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "automaticReplacementAllowed",
          "reservationReleaseAllowed"
        ],
        "properties": {
          "automaticReplacementAllowed": {
            "type": "boolean",
            "const": false
          },
          "reservationReleaseAllowed": {
            "type": "boolean",
            "const": false
          }
        },
        "description": "This report cannot authorize payment replacement or release wallet, spending-limit or credit reservations."
      },
      "RecoveryOperation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "method",
          "path",
          "body",
          "idempotencyKeyRequired",
          "requiredInput"
        ],
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "GET",
              "POST"
            ]
          },
          "path": {
            "type": "string",
            "pattern": "^/v1/payments/[a-fA-F0-9-]{36}/(prepare|wallet-approval(/confirm)?|transaction(/signature|/review|/renew|/close|/broadcast-confirm)?|execute|refresh|next-action|advance|reconcile)$",
            "description": "Reference to the root or active payment. Validate the returned payment identity and use the trusted Route origin; never execute from this report alone."
          },
          "body": {
            "type": "object",
            "additionalProperties": false,
            "required": [],
            "properties": {
              "version": {
                "type": "integer",
                "minimum": 1
              },
              "authorizationId": {
                "type": "string",
                "format": "uuid"
              },
              "approvalId": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          "idempotencyKeyRequired": {
            "type": "boolean"
          },
          "requiredInput": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "paymentIntent",
                "signedTransaction",
                "signature",
                "transactionHash"
              ]
            }
          }
        },
        "description": "Known control fields only. Required signing inputs are named but never included."
      },
      "RecoveryNextStep": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "actor",
          "message",
          "operation"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "prepare-payment",
              "request-intent-approval",
              "sign-intent",
              "prepare-transaction",
              "sign-transaction",
              "submit-transaction",
              "refresh-review",
              "track",
              "continue-leg",
              "advance",
              "reconcile",
              "completed",
              "refunded",
              "cancelled",
              "review-required",
              "confirm-wallet-broadcast",
              "renew-mint",
              "renew-approval",
              "close-payment",
              "renew-source"
            ]
          },
          "actor": {
            "type": "string",
            "enum": [
              "app",
              "wallet",
              "operator",
              "none"
            ]
          },
          "message": {
            "type": "string"
          },
          "operation": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/RecoveryOperation"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "description": "Saved next-step reference without the wallet payload. Use next-action and detailed payment reads to review current operation requirements."
      },
      "RecoveryEvidence": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "source",
          "destination",
          "refund",
          "transactions",
          "settlementDiscrepancies",
          "lastObservedAt"
        ],
        "properties": {
          "source": {
            "$ref": "#/components/schemas/RecoveryStage"
          },
          "destination": {
            "$ref": "#/components/schemas/RecoveryStage"
          },
          "refund": {
            "$ref": "#/components/schemas/RecoveryStage"
          },
          "transactions": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/RecoveryTransaction"
            }
          },
          "settlementDiscrepancies": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/RecoveryDiscrepancy"
            }
          },
          "lastObservedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "RecoveryWalletReservationGroup": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "observed",
          "items",
          "truncated",
          "note"
        ],
        "properties": {
          "observed": {
            "type": "boolean",
            "const": false
          },
          "items": {
            "type": "array",
            "maxItems": 0,
            "items": {
              "$ref": "#/components/schemas/RecoveryWalletReservation"
            }
          },
          "truncated": {
            "type": "boolean",
            "const": false
          },
          "note": {
            "type": "string"
          }
        },
        "description": "Observed distinguishes a saved reservation read from unavailable evidence. Empty unobserved groups do not mean no reservations exist. Truncated means additional records were omitted."
      },
      "RecoveryApiLimitReservationGroup": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "observed",
          "items",
          "truncated",
          "note"
        ],
        "properties": {
          "observed": {
            "type": "boolean",
            "const": false
          },
          "items": {
            "type": "array",
            "maxItems": 0,
            "items": {
              "$ref": "#/components/schemas/RecoveryApiLimitReservation"
            }
          },
          "truncated": {
            "type": "boolean",
            "const": false
          },
          "note": {
            "type": "string"
          }
        },
        "description": "Observed distinguishes a saved reservation read from unavailable evidence. Empty unobserved groups do not mean no reservations exist. Truncated means additional records were omitted."
      },
      "RecoveryCreditReservationGroup": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "observed",
          "items",
          "truncated",
          "note"
        ],
        "properties": {
          "observed": {
            "type": "boolean",
            "const": false
          },
          "items": {
            "type": "array",
            "maxItems": 0,
            "items": {
              "$ref": "#/components/schemas/RecoveryCreditReservation"
            }
          },
          "truncated": {
            "type": "boolean",
            "const": false
          },
          "note": {
            "type": "string"
          }
        },
        "description": "Observed distinguishes a saved reservation read from unavailable evidence. Empty unobserved groups do not mean no reservations exist. Truncated means additional records were omitted."
      },
      "RecoveryReservations": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "wallet",
          "apiLimit",
          "credits"
        ],
        "properties": {
          "wallet": {
            "$ref": "#/components/schemas/RecoveryWalletReservationGroup"
          },
          "apiLimit": {
            "$ref": "#/components/schemas/RecoveryApiLimitReservationGroup"
          },
          "credits": {
            "$ref": "#/components/schemas/RecoveryCreditReservationGroup"
          }
        },
        "description": "Mainnet performs bounded project-scoped saved reservation reads. Testnet returns each group unobserved with an empty items array; it does not inspect mainnet reservation tables."
      },
      "PaymentRecoveryReport": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "schemaVersion",
          "network",
          "paymentId",
          "activePaymentId",
          "preparationId",
          "authorizationId",
          "generatedAt",
          "status",
          "outcome",
          "owner",
          "summary",
          "nextStep",
          "evidence",
          "requiredEvidence",
          "reservations",
          "safety",
          "notice"
        ],
        "properties": {
          "object": {
            "const": "payment_recovery"
          },
          "schemaVersion": {
            "type": "integer",
            "const": 1
          },
          "network": {
            "const": "testnet"
          },
          "paymentId": {
            "type": "string",
            "format": "uuid"
          },
          "activePaymentId": {
            "type": "string",
            "format": "uuid"
          },
          "preparationId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "authorizationId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "outcome": {
            "type": "string",
            "enum": [
              "no-action-issued",
              "awaiting-wallet-action",
              "unsigned-review-expired",
              "signed-not-submitted",
              "submission-uncertain",
              "source-confirmed",
              "destination-pending",
              "settlement-discrepancy",
              "intermediate-held",
              "completed",
              "refunded",
              "closed",
              "operator-review"
            ]
          },
          "owner": {
            "type": "string",
            "enum": [
              "app",
              "wallet",
              "operator",
              "none"
            ]
          },
          "summary": {
            "type": "string"
          },
          "nextStep": {
            "$ref": "#/components/schemas/RecoveryNextStep"
          },
          "evidence": {
            "$ref": "#/components/schemas/RecoveryEvidence"
          },
          "requiredEvidence": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "reservations": {
            "$ref": "#/components/schemas/RecoveryReservations"
          },
          "safety": {
            "$ref": "#/components/schemas/RecoverySafety"
          },
          "notice": {
            "type": "string"
          }
        },
        "description": "Read-only saved evidence for an existing payment. Does not refresh providers or chains, sign, submit, mint, allocate deposits, replace payments, or release reservations. Existing POST /refresh may perform previously authorized managed destination minting; it is not equivalent to this GET. Reports omit credentials, signatures, transaction payloads and raw provider responses. Wallet addresses and transaction hashes remain sensitive operational information."
      },
      "WalletBroadcast": {
        "type": "object",
        "required": [
          "authorizationId",
          "state",
          "createdAt",
          "expiresAt",
          "transactionHash",
          "verifiedAt",
          "method",
          "params",
          "notice"
        ],
        "properties": {
          "authorizationId": {
            "type": "string",
            "format": "uuid"
          },
          "state": {
            "enum": [
              "awaiting-transaction",
              "verified",
              "cancelled"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "transactionHash": {
            "type": [
              "string",
              "null"
            ]
          },
          "verifiedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "method": {
            "enum": [
              "eth_sendTransaction",
              null
            ],
            "description": "null after a finalized cancellation, or once wallet-altered payment-call evidence is recorded for a burn (the handoff is then kept for review and notice explains it). Never open the wallet without params."
          },
          "params": {
            "type": "array",
            "minItems": 0,
            "maxItems": 1,
            "description": "Empty whenever method is null. An altered spending approval keeps its params.",
            "items": {
              "type": "object",
              "description": "Exact EVM transaction including type 0x0, from, to, value, data, chainId, nonce, gas and gasPrice. Preserve every supplied field."
            }
          },
          "notice": {
            "type": "string"
          },
          "cancellation": {
            "type": [
              "object",
              "null"
            ],
            "description": "Immutable finalized nonce cancellation evidence, separate from the payment source transaction."
          }
        }
      },
      "WalletBroadcastRecovery": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "paymentId",
          "authorizationId",
          "state",
          "message",
          "transactionHash",
          "network",
          "sender",
          "nonce",
          "checkedAt",
          "finalized",
          "blockNumber",
          "blockHash",
          "canClose",
          "paymentClosed",
          "automaticResubmissionAllowed"
        ],
        "properties": {
          "object": {
            "const": "wallet_broadcast_recovery"
          },
          "paymentId": {
            "type": "string",
            "format": "uuid"
          },
          "authorizationId": {
            "type": "string",
            "format": "uuid"
          },
          "state": {
            "enum": [
              "not-observed",
              "pending-nonce",
              "original-verified",
              "altered-payment",
              "equivalent-execution",
              "unclassified-sender-transaction",
              "cancellation-pending",
              "cancellation-verified",
              "closed",
              "reported-transaction",
              "unclassified-transaction",
              "different-transaction"
            ],
            "description": "reported-transaction: the reported hash is recorded as pending evidence for the payment and the network does not show it yet (or it is the saved call sent without a handoff); it blocks every action of the payment until a later check classifies or clears it. unclassified-transaction: the network shows the reported transaction but Route cannot verify that the sender signed it (relayed or sponsored execution, L2 system or deposit type, unsigned or unknown envelope, another key); it is recorded and blocks. not-observed is returned only when no hash was supplied. different-transaction is no longer returned (kept so existing clients keep validating); such transactions are now evidence."
          },
          "message": {
            "type": "string"
          },
          "transactionHash": {
            "type": [
              "string",
              "null"
            ]
          },
          "network": {
            "type": "string"
          },
          "sender": {
            "type": "string"
          },
          "nonce": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "checkedAt": {
            "type": "string",
            "format": "date-time"
          },
          "finalized": {
            "type": "boolean"
          },
          "blockNumber": {
            "type": [
              "string",
              "null"
            ]
          },
          "blockHash": {
            "type": [
              "string",
              "null"
            ]
          },
          "canClose": {
            "type": "boolean"
          },
          "paymentClosed": {
            "type": "boolean"
          },
          "automaticResubmissionAllowed": {
            "const": false
          }
        }
      },
      "WalletAlteredTransaction": {
        "type": "object",
        "description": "Review evidence for a wallet transaction that kept the saved payment call (sender, contract, calldata, value and chain) but changed its nonce, fees or transaction type. Returned as error.details with 409 WALLET_TRANSACTION_REVIEW_REQUIRED, recorded in Route's append-only evidence journal and saved as the action's lastError. Route then never submits the saved signature or hands the saved call to the wallet. The same code with reason equivalent-execution records the same payment sent or queued at another nonce (re-quoted, another value or envelope type, or a call to the payment contract), which carries reason, match, pending and transactionData. The same code with reason unclassified-sender-transaction records any other transaction the wallet signed that was reported for the action and is neither the saved transaction nor a recognized cancellation (fail-closed: Route cannot establish that it is not this payment), at any nonce and in any envelope, with contract, observedValue, pending and transactionData. Only a wallet-altered copy carries the observed gas fields, which are optional (observedGas, observedGasPrice, observedMaxFeePerGas). Route never attaches it to the payment and never releases the saved nonce or any reservation. Cancellation cannot close that action afterwards. Do not send replacement funds. Freeze on report (payment scope): every transaction hash reported for any action of a payment to broadcast-recover, broadcast-cancel, broadcast-confirm, /transaction/close or close after manual check (testnet: broadcast-recover, broadcast-cancel and broadcast-confirm) is recorded in Route's append-only evidence journal for the whole payment before Route reads the network or checks the payment's shape, unless it is that action's own saved or wallet-confirmed transaction or its recorded cancellation. Until an inspection shows it is the action's own transaction or a finalized recognized cancellation at the saved nonce (the report is then cleared; a cancellation or nonce proof that is not final yet clears nothing, and broadcast-confirm never clears one), it is pending evidence (reason reported-transaction; recovery state reported-transaction when the network does not show it yet, and it stays pending if the lookup fails); an inspection otherwise classifies the same row as altered-payment, equivalent-execution, unclassified-sender-transaction, or unclassified-transaction (a transaction the network shows that the sender did not verifiably sign: a relayed or sponsored EIP-7702 or ERC-4337 execution, an L2 system or deposit transaction, an unsigned or unknown envelope, or another key). Evidence on any action blocks every action of the payment: Route submits no saved signature (execute), starts no new wallet handoff and prepares no further action (POST /transaction; testnet /prepare and /transaction) with 409 WALLET_TRANSACTION_REVIEW_REQUIRED and the evidence in error.details, and no cancellation or closure releases the payment's holds. Only a spending approval's byte-identical call to the same spender, in any envelope (reason absent, altered-payment), is exempt; it refuses only that approval's own submission. Only Route's audited attribution of the hash to another Route payment with matching terms lifts the block (protocol payments); NEAR and testnet evidence that is not attributable needs operator review. A same-payment copy that nobody reports to Route cannot be seen.",
        "required": [
          "code",
          "message",
          "transactionHash",
          "network",
          "sender",
          "nonce",
          "checkedAt",
          "automaticAttachmentAllowed"
        ],
        "properties": {
          "code": {
            "const": "WALLET_TRANSACTION_REVIEW_REQUIRED"
          },
          "message": {
            "type": "string"
          },
          "transactionHash": {
            "type": "string",
            "pattern": "^0x[0-9a-f]{64}$"
          },
          "network": {
            "type": "string"
          },
          "sender": {
            "type": "string"
          },
          "nonce": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Nonce of the saved action."
          },
          "observedNonce": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[0-9]+$",
            "description": "Nonce of the observed transaction. Absent on reported-transaction evidence, and null where it could not be read (search evidence, or an unclassified-transaction without a nonce)."
          },
          "observedType": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[0-9]+$",
            "description": "Observed envelope type, in decimal: 0 legacy (EIP-155, or without replay protection as evidence only), 1 EIP-2930, 2 EIP-1559, 3 blob, 4 set-code; unclassified-transaction evidence can carry any type the network reports (for example 126 for an OP-stack deposit), or null. Absent on search and reported-transaction evidence."
          },
          "observedGas": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Optional: present only on a wallet-altered copy (no reason), which Route rebuilt from its signed envelope; other evidence lacks it."
          },
          "observedGasPrice": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[0-9]+$",
            "description": "Optional: present only on a wallet-altered copy (no reason), which Route rebuilt from its signed envelope; other evidence lacks it. Null for EIP-1559 transactions."
          },
          "observedMaxFeePerGas": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[0-9]+$",
            "description": "Optional: present only on a wallet-altered copy (no reason), which Route rebuilt from its signed envelope; other evidence lacks it. Set only for EIP-1559 transactions."
          },
          "reason": {
            "enum": [
              "altered-payment",
              "equivalent-execution",
              "unclassified-sender-transaction",
              "unclassified-transaction",
              "reported-transaction"
            ],
            "description": "equivalent-execution: the same payment sent or queued at another nonce. unclassified-sender-transaction: another transaction the sender signed that was reported for the action and is neither the saved transaction nor a recognized cancellation. Absent on a wallet-altered copy of the saved call. unclassified-transaction: a reported transaction the network shows but the sender did not verifiably sign (relayed or sponsored execution, L2 system or deposit type, unsigned or unknown envelope, another key). reported-transaction: a reported hash Route recorded before reading it, still pending (not visible yet, or the lookup failed)."
          },
          "match": {
            "enum": [
              "same-payment",
              "provider-contract"
            ]
          },
          "pending": {
            "type": "boolean",
            "description": "True while the reported transaction is still queued."
          },
          "transactionData": {
            "type": [
              "string",
              "null"
            ]
          },
          "checkedAt": {
            "type": "string",
            "format": "date-time"
          },
          "automaticAttachmentAllowed": {
            "const": false
          },
          "contract": {
            "type": [
              "string",
              "null"
            ],
            "description": "For equivalent-execution and unclassified-sender-transaction evidence: the observed transaction's target (null for a contract creation)."
          },
          "observedValue": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[0-9]+$",
            "description": "For a reported signed transaction: its native value in wei."
          },
          "observedFrom": {
            "type": [
              "string",
              "null"
            ],
            "description": "Only on unclassified-transaction evidence: the from address the network reports (for example a relayer or bundler)."
          },
          "signer": {
            "enum": [
              "other",
              "unverified"
            ],
            "description": "Only on unclassified-transaction evidence: other when the network reports another account as from; unverified when it reports the sender but Route cannot rebuild a sender signature."
          },
          "reported": {
            "type": "object",
            "properties": {
              "operation": {
                "type": "string"
              },
              "reportedAt": {
                "type": "string",
                "format": "date-time"
              }
            },
            "description": "When the evidence started as a reported hash: the operation it was reported to and when. Kept when an inspection classifies the report."
          }
        }
      },
      "StellarSubmissionObservation": {
        "type": [
          "object",
          "null"
        ],
        "additionalProperties": false,
        "properties": {
          "network": {
            "type": "string",
            "enum": [
              "stellar",
              "stellar-testnet"
            ]
          },
          "hash": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "state": {
            "type": "string",
            "enum": [
              "not-observed",
              "expired-unobserved",
              "sequence-consumed",
              "sequence-gap",
              "unavailable"
            ]
          },
          "checkedAt": {
            "type": "string",
            "format": "date-time"
          },
          "ledger": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "closedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "accountSequence": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[0-9]{1,19}$"
          },
          "transactionSequence": {
            "type": "string",
            "pattern": "^[0-9]{1,19}$"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "description": "Saved, hash-bound Stellar observation after a missing receipt. Expiry uses the envelope time bound and a fresh closed ledger. Sequence consumption does not identify which transaction consumed it. This is never permission to replace a transfer or release reservations.",
        "required": [
          "network",
          "hash",
          "state",
          "checkedAt",
          "ledger",
          "closedAt",
          "accountSequence",
          "transactionSequence",
          "expiresAt"
        ]
      },
      "SourceSubmissionObservation": {
        "type": [
          "object",
          "null"
        ],
        "additionalProperties": false,
        "properties": {
          "network": {
            "type": "string",
            "enum": [
              "btc",
              "sol",
              "fogo"
            ]
          },
          "hash": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9]{64,88}$"
          },
          "state": {
            "type": "string",
            "enum": [
              "not-observed",
              "pending",
              "receipt-reported",
              "inputs-conflicted",
              "blockhash-expired",
              "failure-reported",
              "unavailable"
            ]
          },
          "checkedAt": {
            "type": "string",
            "format": "date-time"
          },
          "conflictingHashes": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "pattern": "^[a-f0-9]{64}$"
            }
          },
          "blockHeight": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "lastValidBlockHeight": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          }
        },
        "description": "Hash-bound observation of a saved Bitcoin or Solana/Fogo source action. Reported receipts, spends and errors are not verified settlement or refund proof; they never authorize replacement or reservation release.",
        "required": [
          "network",
          "hash",
          "state",
          "checkedAt",
          "conflictingHashes",
          "blockHeight",
          "lastValidBlockHeight"
        ]
      },
      "PaymentState": {
        "type": "string",
        "enum": [
          "DRAFT",
          "ARCHIVED",
          "CANCELLED",
          "PREPARING",
          "AWAITING_ACTION",
          "WALLET_SUBMISSION_UNKNOWN",
          "SOURCE_PENDING",
          "DESTINATION_PENDING",
          "DELIVERED_PENDING_FINALITY",
          "REFUND_PENDING_FINALITY",
          "VERIFICATION_PENDING",
          "INTERMEDIATE_HELD",
          "COMPLETED",
          "REFUNDED",
          "REQUIRES_ATTENTION",
          "FAILED"
        ],
        "description": "Normalized business payment state. WALLET_SUBMISSION_UNKNOWN means an external wallet may have sent funds and Route has not verified the hash: reconcile the saved action, never resend automatically. INTERMEDIATE_HELD means a composed payment has finalized an intermediate receipt and is waiting for its next authorized step. Workflow/provider status remains separate."
      },
      "ArrivalWarning": {
        "type": "object",
        "required": [
          "code",
          "message",
          "arrivalModel"
        ],
        "description": "Speed priority, a delivery deadline or an Auto-route speed or balanced preference needs end-to-end arrival evidence. Route models it only for reviewed direct paths, and only until the arrival model review expires. Managed CCTP delivery to Stellar also needs Circle attestation timing, whose separate review expiry the message names; after that review lapses the message excludes that path. Derived when read or saved; never stored with the policy. Warnings do not block saving.",
        "properties": {
          "code": {
            "enum": [
              "ARRIVAL_EVIDENCE_LIMITED",
              "ARRIVAL_EVIDENCE_UNAVAILABLE"
            ],
            "description": "ARRIVAL_EVIDENCE_LIMITED: only modeled direct paths can satisfy the setting. ARRIVAL_EVIDENCE_UNAVAILABLE: the model review has lapsed and no route can satisfy it."
          },
          "message": {
            "type": "string"
          },
          "arrivalModel": {
            "type": "object",
            "required": [
              "version",
              "reviewedAt",
              "expiresAt",
              "current"
            ],
            "properties": {
              "version": {
                "const": "arrival-v1"
              },
              "reviewedAt": {
                "type": "string",
                "format": "date-time"
              },
              "expiresAt": {
                "type": "string",
                "format": "date-time"
              },
              "current": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "QuoteSummary": {
        "type": "object",
        "description": "Observation for one provider path. Decimal receipts use destination asset units and estimatedCostUsd uses USD. Missing estimates are null. A recommendation is limited to observed paths and does not guarantee a globally best price or authorize spending.",
        "properties": {
          "received": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|[1-9]\\d*)(\\.\\d+)?$",
            "description": "Estimated recipient amount in destination asset units."
          },
          "minimumReceived": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|[1-9]\\d*)(\\.\\d+)?$",
            "description": "Quoted minimum recipient amount in destination asset units, when available. Later preparation must validate the actual payment terms."
          },
          "estimatedCostUsd": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|[1-9]\\d*)(\\.\\d+)?$",
            "description": "Estimated total cost in USD. When costComplete is false, source gas still needs confirmation and the ranking can change."
          },
          "costComplete": {
            "type": "boolean",
            "description": "Whether quoted total cost is complete; wallet, policy and actual transaction fee checks remain mandatory."
          },
          "legs": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "description": "Number of provider transfers. Multi-leg routes are non-atomic and require later-leg re-quotes after settlement and separate wallet authorization."
          }
        },
        "required": [
          "received",
          "minimumReceived",
          "estimatedCostUsd",
          "costComplete",
          "legs"
        ],
        "additionalProperties": false
      },
      "QuoteBest": {
        "type": "object",
        "description": "Explicit testnet best view. Testnet has no automatic recommendation, so quote and nextAction are null. Use compact/full and an explicit candidate.",
        "properties": {
          "object": {
            "const": "quote"
          },
          "apiVersion": {
            "const": "v1"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "unavailable",
              "expired"
            ],
            "description": "Ready means quote checks passed for wallet preparation, not authorization to spend. Fee confirmation permits only the source-gas deferral. Unavailable or expired has no automatic next action."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "input": {
            "type": "object",
            "properties": {
              "sourceAssetId": {
                "type": "string"
              },
              "destinationAssetId": {
                "type": "string"
              },
              "amount": {
                "type": "string",
                "pattern": "^(0|[1-9]\\d*)(\\.\\d+)?$",
                "description": "Positive decimal quantity in source asset units, within its catalog precision. Not USD or integer base units."
              }
            },
            "required": [
              "sourceAssetId",
              "destinationAssetId",
              "amount"
            ],
            "additionalProperties": false
          },
          "nextAction": {
            "type": "null"
          },
          "network": {
            "const": "testnet"
          },
          "quote": {
            "type": "null"
          }
        },
        "required": [
          "object",
          "apiVersion",
          "id",
          "status",
          "expiresAt",
          "input",
          "nextAction",
          "network",
          "quote"
        ],
        "additionalProperties": false
      },
      "QuoteListCandidate": {
        "type": "object",
        "properties": {
          "candidateId": {
            "type": "string",
            "description": "Use as candidateId to explicitly create a payment for this alternative."
          },
          "status": {
            "enum": [
              "ready-for-preparation",
              "requires-fee-confirmation"
            ]
          },
          "received": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|[1-9]\\d*)(\\.\\d+)?$",
            "description": "Estimated recipient amount in destination asset units."
          },
          "minimumReceived": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|[1-9]\\d*)(\\.\\d+)?$",
            "description": "Quoted minimum recipient amount in destination asset units, when available. Later preparation must validate the actual payment terms."
          },
          "estimatedCostUsd": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(0|[1-9]\\d*)(\\.\\d+)?$",
            "description": "Estimated total cost in USD. When costComplete is false, source gas still needs confirmation and the ranking can change."
          },
          "costComplete": {
            "type": "boolean",
            "description": "Whether quoted total cost is complete; wallet, policy and actual transaction fee checks remain mandatory."
          },
          "legs": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "description": "Number of provider transfers. Multi-leg routes are non-atomic and require later-leg re-quotes after settlement and separate wallet authorization."
          }
        },
        "required": [
          "candidateId",
          "status",
          "received",
          "minimumReceived",
          "estimatedCostUsd",
          "costComplete",
          "legs"
        ],
        "additionalProperties": false
      },
      "QuoteList": {
        "type": "object",
        "description": "Explicit testnet list view. No automatic recommendation or selectable alternatives are inferred; use compact/full to explicitly select Standard or Fast.",
        "properties": {
          "object": {
            "const": "quote"
          },
          "apiVersion": {
            "const": "v1"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "unavailable",
              "expired"
            ],
            "description": "Ready means quote checks passed for wallet preparation, not authorization to spend. Fee confirmation permits only the source-gas deferral. Unavailable or expired has no automatic next action."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "input": {
            "type": "object",
            "properties": {
              "sourceAssetId": {
                "type": "string"
              },
              "destinationAssetId": {
                "type": "string"
              },
              "amount": {
                "type": "string",
                "pattern": "^(0|[1-9]\\d*)(\\.\\d+)?$",
                "description": "Positive decimal quantity in source asset units, within its catalog precision. Not USD or integer base units."
              }
            },
            "required": [
              "sourceAssetId",
              "destinationAssetId",
              "amount"
            ],
            "additionalProperties": false
          },
          "nextAction": {
            "type": "null"
          },
          "network": {
            "const": "testnet"
          },
          "recommendedCandidateId": {
            "type": "null"
          },
          "candidates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuoteListCandidate"
            },
            "maxItems": 0
          }
        },
        "required": [
          "object",
          "apiVersion",
          "id",
          "status",
          "expiresAt",
          "input",
          "nextAction",
          "network",
          "recommendedCandidateId",
          "candidates"
        ],
        "additionalProperties": false
      },
      "QuoteResponse": {
        "description": "Testnet defaults to compact. Full retains diagnostics; explicit best/list never invent a recommendation.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/QuoteBest"
          },
          {
            "$ref": "#/components/schemas/QuoteList"
          },
          {
            "$ref": "#/components/schemas/Quote"
          }
        ]
      }
    }
  },
  "paths": {
    "/assets": {
      "get": {
        "x-required-scope": "catalog:read",
        "operationId": "testnetAssets",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ]
      }
    },
    "/adapters": {
      "get": {
        "x-required-scope": "catalog:read",
        "operationId": "testnetAdapters",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ]
      }
    },
    "/quotes": {
      "post": {
        "x-required-scope": "quotes:write",
        "operationId": "testnetQuote",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "A missing or non-UUID value returns 400 IDEMPOTENCY_REQUIRED and changes nothing; persist a UUID and retry."
          },
          {
            "name": "view",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "best",
                "list",
                "compact",
                "full"
              ],
              "default": "compact"
            },
            "description": "Testnet still defaults to view=compact and requires an explicit payment candidateId. Explicit best/list contain no automatic recommendation; full retains the previous detailed response. Views preserve the saved quote and idempotency identity. Reads never create a payment, refresh providers, extend expiry or add a charge. Invalid or repeated values return 400 INVALID_QUOTE_VIEW before requesting a quote or reserving quote credits."
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResponse"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResponse"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResponse"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "sourceAssetId": {
                    "type": "string"
                  },
                  "destinationAssetId": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string"
                  }
                },
                "required": [
                  "sourceAssetId",
                  "destinationAssetId",
                  "amount"
                ]
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "description": "Testnet still defaults to view=compact and requires an explicit payment candidateId. Explicit best/list contain no automatic recommendation; full retains the previous detailed response. Views preserve the saved quote and idempotency identity. Reads never create a payment, refresh providers, extend expiry or add a charge."
      }
    },
    "/quotes/{id}": {
      "get": {
        "x-required-scope": "quotes:read",
        "operationId": "getTestnetQuote",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "view",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "best",
                "list",
                "compact",
                "full"
              ],
              "default": "compact"
            },
            "description": "Testnet still defaults to view=compact and requires an explicit payment candidateId. Explicit best/list contain no automatic recommendation; full retains the previous detailed response. Views preserve the saved quote and idempotency identity. Reads never create a payment, refresh providers, extend expiry or add a charge. Invalid or repeated values return 400 INVALID_QUOTE_VIEW before requesting a quote or reserving quote credits."
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResponse"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResponse"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResponse"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "description": "Testnet still defaults to view=compact and requires an explicit payment candidateId. Explicit best/list contain no automatic recommendation; full retains the previous detailed response. Views preserve the saved quote and idempotency identity. Reads never create a payment, refresh providers, extend expiry or add a charge."
      }
    },
    "/payments": {
      "get": {
        "x-required-scope": "payments:read",
        "operationId": "testnetPayments",
        "description": "Required scope: payments:read. Lists the key's testnet payments within its policy, newest first, up to limit per page. While hasMore is true, pass nextCursor as cursor to read older payments.",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "archived",
                "all"
              ],
              "default": "active"
            },
            "description": "Testnet payments are never archived: active and all return the same payments, archived returns none."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Opaque nextCursor from the preceding testnet page. Keep the same view; a mainnet cursor is refused with 400 INVALID_CURSOR."
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "network": {
                      "type": "string",
                      "const": "testnet"
                    },
                    "payments": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Payment"
                      }
                    },
                    "view": {
                      "enum": [
                        "active",
                        "archived",
                        "all"
                      ]
                    },
                    "hasMore": {
                      "type": "boolean"
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as cursor to read the next, older page; null on the last page."
                    }
                  },
                  "required": [
                    "object",
                    "network",
                    "payments",
                    "hasMore",
                    "nextCursor"
                  ]
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "network": {
                      "type": "string",
                      "const": "testnet"
                    },
                    "payments": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Payment"
                      }
                    },
                    "view": {
                      "enum": [
                        "active",
                        "archived",
                        "all"
                      ]
                    },
                    "hasMore": {
                      "type": "boolean"
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as cursor to read the next, older page; null on the last page."
                    }
                  },
                  "required": [
                    "object",
                    "network",
                    "payments",
                    "hasMore",
                    "nextCursor"
                  ]
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "network": {
                      "type": "string",
                      "const": "testnet"
                    },
                    "payments": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Payment"
                      }
                    },
                    "view": {
                      "enum": [
                        "active",
                        "archived",
                        "all"
                      ]
                    },
                    "hasMore": {
                      "type": "boolean"
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as cursor to read the next, older page; null on the last page."
                    }
                  },
                  "required": [
                    "object",
                    "network",
                    "payments",
                    "hasMore",
                    "nextCursor"
                  ]
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ]
      },
      "post": {
        "x-required-scope": "payments:write",
        "operationId": "createTestnetPayment",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "A missing or non-UUID value returns 400 IDEMPOTENCY_REQUIRED and changes nothing; persist a UUID and retry."
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "prepare"
                    ]
                  },
                  "quoteId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "candidateId": {
                    "type": "string"
                  }
                },
                "required": [
                  "mode",
                  "quoteId",
                  "candidateId"
                ]
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "description": " Testnet requires an explicit candidateId; quote-ID-only acceptance is mainnet-only."
      }
    },
    "/payments/{id}": {
      "get": {
        "x-required-scope": "payments:read",
        "operationId": "getTestnetPayment",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ]
      }
    },
    "/payments/{id}/preparation": {
      "get": {
        "x-required-scope": "payments:read",
        "operationId": "getTestnetPreparation",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ]
      }
    },
    "/payments/{id}/prepare": {
      "post": {
        "x-required-scope": "payments:write",
        "operationId": "prepareTestnetAction",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "version": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "sender": {
                    "type": "string"
                  },
                  "recipient": {
                    "type": "string"
                  },
                  "destinationFeePayer": {
                    "type": "string"
                  },
                  "maxFee": {
                    "type": "string"
                  },
                  "destinationExecution": {
                    "type": "string",
                    "enum": [
                      "managed",
                      "customer"
                    ],
                    "description": "Circle to Stellar only. Defaults to managed when no destinationFeePayer is supplied. Legacy fee-payer requests remain customer-funded. Fixed for the prepared payment."
                  }
                },
                "required": [
                  "version"
                ],
                "dependentRequired": {
                  "sender": [
                    "recipient",
                    "maxFee"
                  ],
                  "recipient": [
                    "sender",
                    "maxFee"
                  ],
                  "destinationFeePayer": [
                    "sender",
                    "recipient",
                    "maxFee"
                  ],
                  "maxFee": [
                    "sender",
                    "recipient"
                  ]
                },
                "allOf": [
                  {
                    "if": {
                      "properties": {
                        "destinationExecution": {
                          "const": "customer"
                        }
                      },
                      "required": [
                        "destinationExecution"
                      ]
                    },
                    "then": {
                      "required": [
                        "sender",
                        "recipient",
                        "maxFee",
                        "destinationFeePayer"
                      ]
                    }
                  },
                  {
                    "if": {
                      "properties": {
                        "destinationExecution": {
                          "const": "managed"
                        }
                      },
                      "required": [
                        "destinationExecution"
                      ]
                    },
                    "then": {
                      "required": [
                        "sender",
                        "recipient",
                        "maxFee"
                      ],
                      "not": {
                        "required": [
                          "destinationFeePayer"
                        ]
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "description": "Freeze on report (payment scope): every transaction hash reported for any action of a payment to broadcast-recover, broadcast-cancel, broadcast-confirm, /transaction/close or close after manual check (testnet: broadcast-recover, broadcast-cancel and broadcast-confirm) is recorded in Route's append-only evidence journal for the whole payment before Route reads the network or checks the payment's shape, unless it is that action's own saved or wallet-confirmed transaction or its recorded cancellation. Until an inspection shows it is the action's own transaction or a finalized recognized cancellation at the saved nonce (the report is then cleared; a cancellation or nonce proof that is not final yet clears nothing, and broadcast-confirm never clears one), it is pending evidence (reason reported-transaction; recovery state reported-transaction when the network does not show it yet, and it stays pending if the lookup fails); an inspection otherwise classifies the same row as altered-payment, equivalent-execution, unclassified-sender-transaction, or unclassified-transaction (a transaction the network shows that the sender did not verifiably sign: a relayed or sponsored EIP-7702 or ERC-4337 execution, an L2 system or deposit transaction, an unsigned or unknown envelope, or another key). Evidence on any action blocks every action of the payment: Route submits no saved signature (execute), starts no new wallet handoff and prepares no further action (POST /transaction; testnet /prepare and /transaction) with 409 WALLET_TRANSACTION_REVIEW_REQUIRED and the evidence in error.details, and no cancellation or closure releases the payment's holds. Only a spending approval's byte-identical call to the same spender, in any envelope (reason absent, altered-payment), is exempt; it refuses only that approval's own submission. Only Route's audited attribution of the hash to another Route payment with matching terms lifts the block (protocol payments); NEAR and testnet evidence that is not attributable needs operator review. A same-payment copy that nobody reports to Route cannot be seen."
      }
    },
    "/payments/{id}/refresh": {
      "post": {
        "x-required-scope": "payments:write",
        "operationId": "refreshTestnetPayment",
        "description": "Required scope: payments:write. Send {} to request fresh chain and attestation evidence for the current action. Never broadcasts a customer-signed transaction. With managed destination execution, once the burn is finalized and attested, refresh may submit the already-authorized Stellar testnet mint through OpenZeppelin Channels unless managed delivery is paused; Route records one submission claim, so repeated refreshes and background tracking do not submit it again (apart from Route's single guarded automatic re-mint of a lost or failed relay), and destinationExecution reports its progress. A relay submission is not proof of settlement. GET /payments/{id} reads saved state without chain requests.",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {},
                "required": []
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ]
      }
    },
    "/payments/{id}/cancel": {
      "post": {
        "x-required-scope": "payments:write",
        "operationId": "cancelTestnetDraft",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "version": {
                    "type": "integer",
                    "minimum": 1
                  }
                },
                "required": [
                  "version"
                ]
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ]
      }
    },
    "/payments/{id}/transaction": {
      "get": {
        "x-required-scope": "payments:read",
        "operationId": "getTestnetTransaction",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ]
      },
      "post": {
        "x-required-scope": "payments:write",
        "operationId": "prepareTestnetTransaction",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "A missing or non-UUID value returns 400 IDEMPOTENCY_REQUIRED and changes nothing; persist a UUID and retry."
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "version": {
                    "type": "integer",
                    "minimum": 1
                  }
                },
                "required": [
                  "version"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "description": "Freeze on report (payment scope): every transaction hash reported for any action of a payment to broadcast-recover, broadcast-cancel, broadcast-confirm, /transaction/close or close after manual check (testnet: broadcast-recover, broadcast-cancel and broadcast-confirm) is recorded in Route's append-only evidence journal for the whole payment before Route reads the network or checks the payment's shape, unless it is that action's own saved or wallet-confirmed transaction or its recorded cancellation. Until an inspection shows it is the action's own transaction or a finalized recognized cancellation at the saved nonce (the report is then cleared; a cancellation or nonce proof that is not final yet clears nothing, and broadcast-confirm never clears one), it is pending evidence (reason reported-transaction; recovery state reported-transaction when the network does not show it yet, and it stays pending if the lookup fails); an inspection otherwise classifies the same row as altered-payment, equivalent-execution, unclassified-sender-transaction, or unclassified-transaction (a transaction the network shows that the sender did not verifiably sign: a relayed or sponsored EIP-7702 or ERC-4337 execution, an L2 system or deposit transaction, an unsigned or unknown envelope, or another key). Evidence on any action blocks every action of the payment: Route submits no saved signature (execute), starts no new wallet handoff and prepares no further action (POST /transaction; testnet /prepare and /transaction) with 409 WALLET_TRANSACTION_REVIEW_REQUIRED and the evidence in error.details, and no cancellation or closure releases the payment's holds. Only a spending approval's byte-identical call to the same spender, in any envelope (reason absent, altered-payment), is exempt; it refuses only that approval's own submission. Only Route's audited attribution of the hash to another Route payment with matching terms lifts the block (protocol payments); NEAR and testnet evidence that is not attributable needs operator review. A same-payment copy that nobody reports to Route cannot be seen."
      }
    },
    "/payments/{id}/transaction/signature": {
      "post": {
        "x-required-scope": "payments:write",
        "operationId": "saveTestnetSignature",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "authorizationId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "signedTransaction": {
                    "type": "string",
                    "maxLength": 100000
                  }
                },
                "required": [
                  "authorizationId",
                  "signedTransaction"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/payments/{id}/execute": {
      "post": {
        "x-required-scope": "payments:write",
        "operationId": "executeTestnetPayment",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "authorizationId": {
                    "type": "string",
                    "format": "uuid"
                  }
                },
                "required": [
                  "authorizationId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "description": "Required scope: payments:write. Once unresolved review evidence is recorded for the action, execute returns 409 WALLET_TRANSACTION_REVIEW_REQUIRED with the WalletAlteredTransaction evidence in error.details before any external read, whatever the account nonces show, and the database refuses the same submission; nothing is sent. Freeze on report (payment scope): every transaction hash reported for any action of a payment to broadcast-recover, broadcast-cancel, broadcast-confirm, /transaction/close or close after manual check (testnet: broadcast-recover, broadcast-cancel and broadcast-confirm) is recorded in Route's append-only evidence journal for the whole payment before Route reads the network or checks the payment's shape, unless it is that action's own saved or wallet-confirmed transaction or its recorded cancellation. Until an inspection shows it is the action's own transaction or a finalized recognized cancellation at the saved nonce (the report is then cleared; a cancellation or nonce proof that is not final yet clears nothing, and broadcast-confirm never clears one), it is pending evidence (reason reported-transaction; recovery state reported-transaction when the network does not show it yet, and it stays pending if the lookup fails); an inspection otherwise classifies the same row as altered-payment, equivalent-execution, unclassified-sender-transaction, or unclassified-transaction (a transaction the network shows that the sender did not verifiably sign: a relayed or sponsored EIP-7702 or ERC-4337 execution, an L2 system or deposit transaction, an unsigned or unknown envelope, or another key). Evidence on any action blocks every action of the payment: Route submits no saved signature (execute), starts no new wallet handoff and prepares no further action (POST /transaction; testnet /prepare and /transaction) with 409 WALLET_TRANSACTION_REVIEW_REQUIRED and the evidence in error.details, and no cancellation or closure releases the payment's holds. Only a spending approval's byte-identical call to the same spender, in any envelope (reason absent, altered-payment), is exempt; it refuses only that approval's own submission. Only Route's audited attribution of the hash to another Route payment with matching terms lifts the block (protocol payments); NEAR and testnet evidence that is not attributable needs operator review. A same-payment copy that nobody reports to Route cannot be seen."
      }
    },
    "/policy": {
      "get": {
        "operationId": "readPolicy",
        "summary": "readPolicy",
        "description": "Access only the key’s assigned policy. Requires policy:read. New testnet policy limits use TEST_USDC; legacy shared policies keep USD values without treating test tokens as dollars.",
        "x-required-scope": "policy:read",
        "responses": {
          "200": {
            "description": "Success (or an idempotent replay)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Policy"
                }
              }
            }
          },
          "default": {
            "description": "Error. See error.code and X-Request-Id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          }
        ]
      },
      "put": {
        "operationId": "savePolicy",
        "summary": "savePolicy",
        "description": "Access only the key’s assigned policy. Requires policy:write. New testnet policy limits use TEST_USDC; legacy shared policies keep USD values without treating test tokens as dollars.",
        "x-required-scope": "policy:write",
        "responses": {
          "200": {
            "description": "Success (or an idempotent replay)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Policy"
                }
              }
            }
          },
          "default": {
            "description": "Error. See error.code and X-Request-Id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PolicyInput"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          }
        ]
      }
    },
    "/payments/{id}/next-action": {
      "get": {
        "operationId": "getTestnetPaymentNextAction",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Saved-state action snapshot. Not an authorization or a guarantee of fresh readiness.",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Save when reporting an integration problem."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentNextAction"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "summary": "Read the next payment action",
        "description": "Required scope: payments:read. Read a normalized projection of saved payment, preparation and transaction state. Does not sign, broadcast, refresh chain evidence or create a provider deposit. Separate app, wallet and operator steps; preserve identifiers and reread after each operation. Unknown future actions must pause automatic execution.",
        "x-required-scope": "payments:read"
      }
    },
    "/payments/{id}/recovery": {
      "get": {
        "operationId": "getTestnetPaymentRecovery",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Saved recovery report. generatedAt is report creation time, not a fresh chain observation. No recovery action is authorized.",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Save when reporting an integration problem."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentRecoveryReport"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "summary": "Read saved payment recovery evidence",
        "description": "Required scope: payments:read. Read a sanitized saved-state recovery report for the accessible root or active payment, without provider or chain requests. Does not sign, broadcast, perform managed minting, allocate deposits, replace payments or release reservations. Mainnet includes bounded saved reservation reads; testnet reservation groups are unobserved. Existing POST /refresh is separate and may advance previously authorized managed destination delivery.",
        "x-required-scope": "payments:read"
      }
    },
    "/payments/{id}/transaction/broadcast": {
      "post": {
        "operationId": "testnetBeginWalletBroadcast",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "authorizationId"
                ],
                "properties": {
                  "authorizationId": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "summary": "beginWalletBroadcast",
        "description": "Required scope: payments:write. Reserve exclusive wallet submission of the current unsigned EVM action after fresh readiness, policy and budget checks. Returns walletBroadcast with eth_sendTransaction params. No network send occurs. Preserve the same authorizationId. An existing handoff is replayed; do not automatically invoke the wallet twice. Route signature, execute and review calls are blocked for this action. Once review evidence is recorded for a burn or transfer (a wallet-altered payment call, broadcast-recover state altered-payment; the same payment at another nonce; or another reported transaction the wallet signed, state unclassified-sender-transaction), a new handoff returns 409 WALLET_TRANSACTION_REVIEW_REQUIRED with that WalletAlteredTransaction evidence in error.details, before any external read: nothing is reserved and no eth_sendTransaction params are returned, because the wallet would send the saved call too. An existing handoff is still replayed and nothing is sent, but with method null, empty params and a review notice. An altered spending approval moves no funds and does not block its handoff or remove its params; the same payment found at another nonce, or an unclassified sender transaction, blocks an approval's handoff too. While a recovery, cancellation or close check for the action is reading the network, it returns 409 WALLET_EVIDENCE_CHECK_IN_PROGRESS (details.retryable: true, details.retryAfterSeconds) before any network read; the check clears it when it records what it found, and it lapses after 2 minutes. Freeze on report (payment scope): every transaction hash reported for any action of a payment to broadcast-recover, broadcast-cancel, broadcast-confirm, /transaction/close or close after manual check (testnet: broadcast-recover, broadcast-cancel and broadcast-confirm) is recorded in Route's append-only evidence journal for the whole payment before Route reads the network or checks the payment's shape, unless it is that action's own saved or wallet-confirmed transaction or its recorded cancellation. Until an inspection shows it is the action's own transaction or a finalized recognized cancellation at the saved nonce (the report is then cleared; a cancellation or nonce proof that is not final yet clears nothing, and broadcast-confirm never clears one), it is pending evidence (reason reported-transaction; recovery state reported-transaction when the network does not show it yet, and it stays pending if the lookup fails); an inspection otherwise classifies the same row as altered-payment, equivalent-execution, unclassified-sender-transaction, or unclassified-transaction (a transaction the network shows that the sender did not verifiably sign: a relayed or sponsored EIP-7702 or ERC-4337 execution, an L2 system or deposit transaction, an unsigned or unknown envelope, or another key). Evidence on any action blocks every action of the payment: Route submits no saved signature (execute), starts no new wallet handoff and prepares no further action (POST /transaction; testnet /prepare and /transaction) with 409 WALLET_TRANSACTION_REVIEW_REQUIRED and the evidence in error.details, and no cancellation or closure releases the payment's holds. Only a spending approval's byte-identical call to the same spender, in any envelope (reason absent, altered-payment), is exempt; it refuses only that approval's own submission. Only Route's audited attribution of the hash to another Route payment with matching terms lifts the block (protocol payments); NEAR and testnet evidence that is not attributable needs operator review. A same-payment copy that nobody reports to Route cannot be seen.",
        "x-required-scope": "payments:write"
      }
    },
    "/payments/{id}/transaction/broadcast-confirm": {
      "post": {
        "operationId": "testnetConfirmWalletBroadcast",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "A Route testnet result. See testnet-api.md for lifecycle and readiness semantics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "authorizationId",
                  "transactionHash"
                ],
                "properties": {
                  "authorizationId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "transactionHash": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{64}$"
                  }
                }
              }
            }
          }
        },
        "summary": "confirmWalletBroadcast",
        "description": "Required scope: payments:write. Report the hash returned by the wallet for a previously reserved handoff. Route independently reconstructs the signed legacy transaction and verifies all fields and the signer before recording submission. This endpoint never broadcasts. It remains available after review expiry or an execution pause; the current API key must still have payment access. Same hash replays safely. 409 WALLET_TRANSACTION_NOT_FOUND: retry the same hash after bounded backoff. 409 WALLET_TRANSACTION_REVIEW_REQUIRED: the wallet changed the nonce, fees or transaction type but kept the exact payment call (sender, contract, calldata, value and chain); error.details is WalletAlteredTransaction evidence. Route records it permanently and as the action's lastError, never attaches it, and keeps the saved nonce and every reservation. The payment requires review (paymentState REQUIRES_ATTENTION, next action review-required) For a burn or transfer, cancellation can no longer close it (an altered spending approval moves no funds and does not block closure). The evidence remains if the exact original is confirmed later. Do not send replacement funds. Other mismatches (WALLET_TRANSACTION_MISMATCH) and conflicts (WALLET_TRANSACTION_CONFLICT) require reconciliation. Submission is not verified destination delivery. Freeze on report (payment scope): every transaction hash reported for any action of a payment to broadcast-recover, broadcast-cancel, broadcast-confirm, /transaction/close or close after manual check (testnet: broadcast-recover, broadcast-cancel and broadcast-confirm) is recorded in Route's append-only evidence journal for the whole payment before Route reads the network or checks the payment's shape, unless it is that action's own saved or wallet-confirmed transaction or its recorded cancellation. Until an inspection shows it is the action's own transaction or a finalized recognized cancellation at the saved nonce (the report is then cleared; a cancellation or nonce proof that is not final yet clears nothing, and broadcast-confirm never clears one), it is pending evidence (reason reported-transaction; recovery state reported-transaction when the network does not show it yet, and it stays pending if the lookup fails); an inspection otherwise classifies the same row as altered-payment, equivalent-execution, unclassified-sender-transaction, or unclassified-transaction (a transaction the network shows that the sender did not verifiably sign: a relayed or sponsored EIP-7702 or ERC-4337 execution, an L2 system or deposit transaction, an unsigned or unknown envelope, or another key). Evidence on any action blocks every action of the payment: Route submits no saved signature (execute), starts no new wallet handoff and prepares no further action (POST /transaction; testnet /prepare and /transaction) with 409 WALLET_TRANSACTION_REVIEW_REQUIRED and the evidence in error.details, and no cancellation or closure releases the payment's holds. Only a spending approval's byte-identical call to the same spender, in any envelope (reason absent, altered-payment), is exempt; it refuses only that approval's own submission. Only Route's audited attribution of the hash to another Route payment with matching terms lifts the block (protocol payments); NEAR and testnet evidence that is not attributable needs operator review. A same-payment copy that nobody reports to Route cannot be seen. Without a handoff to confirm, a hash on record for review for the action (recorded by this report) returns 409 WALLET_TRANSACTION_REVIEW_REQUIRED with that evidence in error.details instead of 404 WALLET_BROADCAST_NOT_FOUND. A testnet action takes reports from /prepare on, before /transaction requested its authorization: broadcast-recover inspects and records the hash, broadcast-confirm returns the 409 above, and /transaction is then refused (the database refuses the authorization too).",
        "x-required-scope": "payments:write"
      }
    },
    "/payments/{id}/transaction/broadcast-recover": {
      "post": {
        "operationId": "testnetRecoverWalletBroadcast",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Verified recovery observation or idempotent closed result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletBroadcastRecovery"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "authorizationId"
                ],
                "properties": {
                  "authorizationId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "transactionHash": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{64}$"
                  }
                }
              }
            }
          }
        },
        "summary": "Recover wallet submission",
        "description": "Check the saved wallet handoff, optionally using transactionHash. Without a hash, bounded canonical sender/nonce lookup locates an included transaction; pending transactions may still require the wallet hash. An exact original transaction is verified and registered for normal tracking. Missing history, unavailable RPC and an unobserved hash never prove cancellation. This operation never sends funds or releases reservations. Requires payments:write. Five new chain checks per action per minute. State altered-payment: the observed transaction is the exact payment call with a changed nonce, fee or transaction type. Route records it as review evidence (WalletAlteredTransaction), never attaches it, keeps all reservations and reports canClose: false for this action. A transaction the wallet signed that is the same payment without being the saved call (re-quoted, another value or envelope type, an unreadable call to the payment contract, or any call to its provider contracts), sent or still queued at any nonce, returns state equivalent-execution and is recorded the same way. Any other transaction the wallet signed that is not the recognized self-cancellation of the saved nonce, at any nonce and in any envelope, returns state unclassified-sender-transaction and is recorded the same way (fail-closed). A transaction the sender did not verifiably sign (another key, a relayer, an L2 system or deposit type) returns state unclassified-transaction and is recorded the same way. An observation is recorded even if the check outlives its 2-minute in-progress window while a submission or handoff starts. An observation is recorded even if the caller loses access during the check. Freeze on report (payment scope): every transaction hash reported for any action of a payment to broadcast-recover, broadcast-cancel, broadcast-confirm, /transaction/close or close after manual check (testnet: broadcast-recover, broadcast-cancel and broadcast-confirm) is recorded in Route's append-only evidence journal for the whole payment before Route reads the network or checks the payment's shape, unless it is that action's own saved or wallet-confirmed transaction or its recorded cancellation. Until an inspection shows it is the action's own transaction or a finalized recognized cancellation at the saved nonce (the report is then cleared; a cancellation or nonce proof that is not final yet clears nothing, and broadcast-confirm never clears one), it is pending evidence (reason reported-transaction; recovery state reported-transaction when the network does not show it yet, and it stays pending if the lookup fails); an inspection otherwise classifies the same row as altered-payment, equivalent-execution, unclassified-sender-transaction, or unclassified-transaction (a transaction the network shows that the sender did not verifiably sign: a relayed or sponsored EIP-7702 or ERC-4337 execution, an L2 system or deposit transaction, an unsigned or unknown envelope, or another key). Evidence on any action blocks every action of the payment: Route submits no saved signature (execute), starts no new wallet handoff and prepares no further action (POST /transaction; testnet /prepare and /transaction) with 409 WALLET_TRANSACTION_REVIEW_REQUIRED and the evidence in error.details, and no cancellation or closure releases the payment's holds. Only a spending approval's byte-identical call to the same spender, in any envelope (reason absent, altered-payment), is exempt; it refuses only that approval's own submission. Only Route's audited attribution of the hash to another Route payment with matching terms lifts the block (protocol payments); NEAR and testnet evidence that is not attributable needs operator review. A same-payment copy that nobody reports to Route cannot be seen. A signed testnet authorization without a handoff can report a hash here too: it is inspected and recorded, and nothing closes. A testnet action takes reports from /prepare on, before /transaction requested its authorization: the hash is inspected and recorded, nothing closes, and /transaction is then refused while it is open.",
        "x-required-scope": "payments:write"
      }
    },
    "/payments/{id}/transaction/broadcast-cancel": {
      "post": {
        "operationId": "testnetCancelWalletBroadcast",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Verified recovery observation or idempotent closed result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletBroadcastRecovery"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "authorizationId",
                  "transactionHash"
                ],
                "properties": {
                  "authorizationId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "transactionHash": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{64}$"
                  }
                }
              }
            }
          }
        },
        "summary": "Close a verified cancelled wallet submission",
        "description": "Explicitly close an unfunded standalone payment using a finalized zero-value empty-data self-transaction at the saved EVM nonce. Route verifies the signature, canonical receipt, empty code/logs, exact intrinsic gas and finality. Releases unused payment credits and API-limit holds once; quote charges and network fees remain. Never broadcasts a cancellation. Composed transfers and destination mint actions require separate review. Remains available after review expiry or execution pause with payment access. A recorded wallet-altered burn or transfer (recovery state altered-payment, or 409 WALLET_TRANSACTION_REVIEW_REQUIRED from confirmation) blocks closure of that action: canClose is false, and closing returns 409 WALLET_CANCELLATION_REVIEW_REQUIRED (SOURCE_CANCELLATION_REVIEW_REQUIRED or COMPOSED_CANCELLATION_REVIEW_REQUIRED for saved-signature and composed sources). An altered spending approval moves no funds and does not block closure. Report every wallet transaction hash before closing. A same-payment copy reported with transactionHash (state equivalent-execution), or any other transaction the wallet signed (state unclassified-sender-transaction, which blocks closing an approval too), is recorded and refuses the close. A cancellation whose check outlived its 2-minute in-progress window returns 409 WALLET_EVIDENCE_CHECK_EXPIRED (details.retryable true) and closes nothing. Freeze on report (payment scope): every transaction hash reported for any action of a payment to broadcast-recover, broadcast-cancel, broadcast-confirm, /transaction/close or close after manual check (testnet: broadcast-recover, broadcast-cancel and broadcast-confirm) is recorded in Route's append-only evidence journal for the whole payment before Route reads the network or checks the payment's shape, unless it is that action's own saved or wallet-confirmed transaction or its recorded cancellation. Until an inspection shows it is the action's own transaction or a finalized recognized cancellation at the saved nonce (the report is then cleared; a cancellation or nonce proof that is not final yet clears nothing, and broadcast-confirm never clears one), it is pending evidence (reason reported-transaction; recovery state reported-transaction when the network does not show it yet, and it stays pending if the lookup fails); an inspection otherwise classifies the same row as altered-payment, equivalent-execution, unclassified-sender-transaction, or unclassified-transaction (a transaction the network shows that the sender did not verifiably sign: a relayed or sponsored EIP-7702 or ERC-4337 execution, an L2 system or deposit transaction, an unsigned or unknown envelope, or another key). Evidence on any action blocks every action of the payment: Route submits no saved signature (execute), starts no new wallet handoff and prepares no further action (POST /transaction; testnet /prepare and /transaction) with 409 WALLET_TRANSACTION_REVIEW_REQUIRED and the evidence in error.details, and no cancellation or closure releases the payment's holds. Only a spending approval's byte-identical call to the same spender, in any envelope (reason absent, altered-payment), is exempt; it refuses only that approval's own submission. Only Route's audited attribution of the hash to another Route payment with matching terms lifts the block (protocol payments); NEAR and testnet evidence that is not attributable needs operator review. A same-payment copy that nobody reports to Route cannot be seen.",
        "x-required-scope": "payments:write"
      }
    },
    "/payments/{id}/transaction/renew": {
      "post": {
        "operationId": "testnetRenewStellarMint",
        "parameters": [
          {
            "name": "Route-Network",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "testnet"
              ]
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "A missing or non-UUID value returns 400 IDEMPOTENCY_REQUIRED and changes nothing; persist a UUID and retry."
          }
        ],
        "responses": {
          "200": {
            "description": "Identical renewal replay; the original replacement is returned without sending.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "Replacement mint prepared for a fresh wallet signature.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResult"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or revoked API key.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope, project or key restriction.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource or unreleased operation.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State, network, expiry, policy or readiness conflict.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Back off and retry the same request.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Upstream verification unavailable. Do not create another transfer.",
            "headers": {
              "X-Request-Id": {
                "description": "Save this identifier when reporting an integration problem.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "RouteKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "authorizationId"
                ],
                "properties": {
                  "authorizationId": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "summary": "Renew an expired customer-signed Stellar mint",
        "description": "Required scope: payments:write. Only the current customer CCTP Stellar mint with a saved signature and no recorded submission attempt is eligible. Route verifies the exact old signed hash, a fresh closed ledger past its finite time bound and an unused account sequence, then simulates the same mint within its existing fee budget. Returns a new unsigned authorization; no transaction is submitted. Sign the new payload before executing. Persist a UUID Idempotency-Key and replay it after an uncertain response. Submitted, ambiguous, already minted or sequence-consumed transactions require reconciliation. Source burns cannot be renewed through this endpoint.",
        "x-required-scope": "payments:write"
      }
    }
  }
}
