{
	"openapi": "3.1.0",
	"info": {
		"title": "Khalani API",
		"version": "1.1.0",
		"description": "One order API for swapping, bridging and converting tokens across chains.\n\n- Request and response bodies are JSON. Every amount is a decimal string of integer base units, never a number.\n- Authenticated routes take your API key in the `X-API-Key` header. Call them from your backend only.\n- Every response carries an `x-request-id` header. Quote it, with the `orderId`, when you contact support.\n- Quotes and builds are single-use answers: do not cache them."
	},
	"servers": [
		{
			"url": "https://api.hyperstream.dev"
		}
	],
	"tags": [
		{
			"name": "Trading",
			"description": "Discover what you can trade, price it, and build orders."
		},
		{
			"name": "Orders",
			"description": "Track and cancel orders."
		},
		{
			"name": "Service",
			"description": "Service status."
		}
	],
	"paths": {
		"/v2/params": {
			"get": {
				"operationId": "getParams",
				"summary": "List tradable tokens and your terms",
				"description": "Every token you can trade, each with its two fixed fees, and your commercial terms. Any listed token trades against any\nother, so pairs are not enumerated.\n\nNot rate limited and not paused during maintenance, so it doubles as a readiness check for your key. The minimum trade\nsize is not here: `/v2/quote` returns it when a size is too small.",
				"tags": ["Trading"],
				"security": [
					{
						"ApiKeyAuth": []
					}
				],
				"responses": {
					"200": {
						"description": "Tokens and terms.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ParamsResponse"
								},
								"example": {
									"tokens": [
										{
											"chainId": 42161,
											"token": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
											"symbol": "USDC",
											"decimals": 6,
											"depositFee": "150000",
											"withdrawFee": "150000"
										},
										{
											"chainId": 8453,
											"token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
											"symbol": "USDC",
											"decimals": 6,
											"depositFee": "150000",
											"withdrawFee": "150000"
										}
									],
									"terms": {
										"operatorBps": 3,
										"commissionBps": 2,
										"commissionWallet": "0x1c0ce7f3a2d4ab69a33e4a8f5b9a3c4d2e1f0a9b",
										"orderTtl": 3600
									}
								}
							}
						}
					},
					"401": {
						"description": "The `X-API-Key` header is missing.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "X-API-Key required"
								}
							}
						}
					},
					"403": {
						"description": "The key is unknown or past its rotation window, or your integrator registry row is disabled or invalid. A `403` is always about your account: do not retry.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Unknown or inactive integrator"
								}
							}
						}
					},
					"500": {
						"description": "Unhandled failure. Retry once, then escalate with the `x-request-id` response header.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/NamedError"
								},
								"example": {
									"message": "Internal Error",
									"name": "InternalErrorException"
								}
							}
						}
					},
					"503": {
						"description": "Your terms could not be read from the hub. Never about your key or account. Retryable.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Integrator terms are temporarily unreadable"
								}
							}
						}
					}
				}
			}
		},
		"/v2/quote": {
			"get": {
				"operationId": "getQuote",
				"summary": "Quote a trade",
				"description": "Prices one direction and size without creating an order. Nothing is stored: `build` carries a signed attestation, valid\nfor five minutes, that pins `/v2/build` to these numbers.\n\n| `mode` | Send | Get back |\n|---|---|---|\n| `exact_input` (default) | `srcAmount` | `receive.amount`, what the depositor gets |\n| `exact_output` | `outcomeAmount` | `spend.amount`, the smallest deposit that reaches it |\n\nSend exactly the amount `mode` names: both, neither, or the other one is a `400`.\n\nA `200` means the size is fillable now. In `exact_input`, too small is a `400` carrying `detail.minSrcAmount`.\nIn `exact_output`, inspect `spend.amount`: the required deposit includes fees even for a small requested outcome.\nToo large is a `409` carrying\n`maxSrcAmount` (`exact_input`) or `maxOutcomeAmount` (`exact_output`). Re-quote at the returned figure.",
				"tags": ["Trading"],
				"security": [
					{
						"ApiKeyAuth": []
					}
				],
				"parameters": [
					{
						"name": "fromChainId",
						"in": "query",
						"required": true,
						"description": "Source spoke chain id.",
						"schema": {
							"type": "integer",
							"minimum": 0
						},
						"example": 42161
					},
					{
						"name": "from",
						"in": "query",
						"required": true,
						"description": "Source spoke-token address. TRON accepts base58 or hex41.",
						"schema": {
							"type": "string"
						},
						"example": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
					},
					{
						"name": "toChainId",
						"in": "query",
						"required": true,
						"description": "Destination spoke chain id.",
						"schema": {
							"type": "integer",
							"minimum": 0
						},
						"example": 8453
					},
					{
						"name": "to",
						"in": "query",
						"required": true,
						"description": "Destination spoke-token address. TRON accepts base58 or hex41.",
						"schema": {
							"type": "string"
						},
						"example": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
					},
					{
						"name": "mode",
						"in": "query",
						"required": false,
						"description": "Which side you fix: `exact_input` sends `srcAmount`, `exact_output` sends `outcomeAmount`.",
						"schema": {
							"default": "exact_input",
							"type": "string",
							"enum": ["exact_input", "exact_output"]
						},
						"example": "exact_input"
					},
					{
						"name": "srcAmount",
						"in": "query",
						"required": false,
						"description": "What the depositor spends, in source base units. Required when `mode` is `exact_input`; rejected otherwise.",
						"schema": {
							"type": "string",
							"pattern": "^[1-9]\\d*$"
						},
						"example": "100000000"
					},
					{
						"name": "outcomeAmount",
						"in": "query",
						"required": false,
						"description": "What the depositor should receive, in destination base units. Required when `mode` is `exact_output`; rejected otherwise.",
						"schema": {
							"type": "string",
							"pattern": "^[1-9]\\d*$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Fillable now. Show `spend` and `receive`; send `build` to `/v2/build`.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/QuoteResponse"
								},
								"example": {
									"spend": {
										"chainId": 42161,
										"token": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
										"symbol": "USDC",
										"decimals": 6,
										"amount": "100000000"
									},
									"receive": {
										"chainId": 8453,
										"token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
										"symbol": "USDC",
										"decimals": 6,
										"amount": "99620254"
									},
									"details": {
										"intentOutcomeRate": "999700000000000000",
										"protocolFee": "329910"
									},
									"build": {
										"srcToken": {
											"chainId": 42161,
											"token": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
										},
										"dstToken": {
											"chainId": 8453,
											"token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
										},
										"amount": "100000000",
										"intentOutcomeRate": "999700000000000000",
										"terms": {
											"flatFee": "300000000000000000",
											"expiresAt": "1787000000",
											"signature": "0x60ce0a47bc64e07a5437de5fd4e6008bce46756d4d7c971710283924888b2a137a91ed09461b5848bb2b7341f5c258da3f97853e73662275f047e0c3c20882211b"
										}
									}
								}
							}
						}
					},
					"400": {
						"description": "Invalid query (`ValidationError`), an unsupported token, or an `exact_input` size below the minimum (`Error` with `detail.minSrcAmount`).",
						"content": {
							"application/json": {
								"schema": {
									"anyOf": [
										{
											"$ref": "#/components/schemas/ValidationError"
										},
										{
											"$ref": "#/components/schemas/Error"
										}
									]
								},
								"example": {
									"error": "Requested amount is below what the solver will fill",
									"detail": {
										"minSrcAmount": "5000000"
									}
								}
							}
						}
					},
					"401": {
						"description": "The `X-API-Key` header is missing.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "X-API-Key required"
								}
							}
						}
					},
					"403": {
						"description": "The key is unknown or past its rotation window, or your integrator registry row is disabled or invalid. A `403` is always about your account: do not retry.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Unknown or inactive integrator"
								}
							}
						}
					},
					"404": {
						"description": "Source and destination are the same asset.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Source and destination resolve to the same mToken"
								}
							}
						}
					},
					"409": {
						"description": "Larger than what can be filled now. Re-quote at `detail.maxSrcAmount` or `detail.maxOutcomeAmount`.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Requested amount exceeds what the solver can fill",
									"detail": {
										"maxSrcAmount": "250000000000"
									}
								}
							}
						}
					},
					"429": {
						"description": "Rate limited per integrator and per IP. No `Retry-After`; back off and retry.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/RateLimitError"
								},
								"example": {
									"errorCode": "RATE_LIMITED",
									"message": "Too many requests, please retry later"
								}
							}
						}
					},
					"500": {
						"description": "Unhandled failure. Retry once, then escalate with the `x-request-id` response header.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/NamedError"
								},
								"example": {
									"message": "Internal Error",
									"name": "InternalErrorException"
								}
							}
						}
					},
					"503": {
						"description": "Temporarily unavailable: your terms could not be read, a price or fee configuration is missing, or no solver can serve the direction (`Error`), or the API is in maintenance (`NamedError` with `Retry-After`). The variants cannot be told apart reliably, so cap your retries.",
						"headers": {
							"Retry-After": {
								"description": "Seconds to wait. Sent only by the maintenance response.",
								"schema": {
									"type": "integer"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"anyOf": [
										{
											"$ref": "#/components/schemas/Error"
										},
										{
											"$ref": "#/components/schemas/NamedError"
										}
									]
								},
								"example": {
									"name": "MaintenanceException",
									"message": "SystemMaintenance"
								}
							}
						}
					}
				}
			}
		},
		"/v2/build": {
			"post": {
				"operationId": "buildOrder",
				"summary": "Build an order",
				"description": "Turns a quote into an order and returns what the depositor's wallet must send. Send `quote.build` unchanged, plus\n`depositor` and, where required, `payoutAddr` and `refundAddr`. Contract-wallet depositors must pass both recipients\nexplicitly. Use a default only when the user controls that address on the relevant payout or refund chain.\n\n- **EVM source:** `approveTxs` (only if the allowance is short) then `depositTx`, sent in order from `depositor`.\n- **Non-EVM source (TRON):** a `depositAddress`; transfer exactly `expectedAmount` to it with enough time for source-chain\n  confirmation and hub publication before `deadline`.\n\nNot idempotent: every successful call creates a new order. Validation failures happen before order creation, but a 500\nor 502 may leave a reserved TRON deposit address or an order record without tracking. An error is not a usable deposit\nplan; do not fund a recovered order without confirming it with Khalani. Back off and retry at most once, then contact\nKhalani with the `x-request-id`. Repeated retries can exhaust the deposit-address pool. If a call returned no response,\nlook for its order with `GET /v2/orders?depositor=…` before you build again. The order's deadline\nis `orderTtl` seconds from this call, not from the deposit. On every rail, the deadline is the intent's publication expiry:\nbudget source-chain confirmation and hub publication. If insufficient time remains, rebuild **before sending funds**.\nA deposit that cannot publish before expiry requires operator recovery.",
				"tags": ["Trading"],
				"security": [
					{
						"ApiKeyAuth": []
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"$ref": "#/components/schemas/BuildRequest"
							},
							"example": {
								"srcToken": {
									"chainId": 42161,
									"token": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
								},
								"dstToken": {
									"chainId": 8453,
									"token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
								},
								"amount": "100000000",
								"intentOutcomeRate": "999700000000000000",
								"terms": {
									"flatFee": "300000000000000000",
									"expiresAt": "1787000000",
									"signature": "0x60ce0a47bc64e07a5437de5fd4e6008bce46756d4d7c971710283924888b2a137a91ed09461b5848bb2b7341f5c258da3f97853e73662275f047e0c3c20882211b"
								},
								"depositor": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4"
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "The order is created in `pending_deposit`. Persist `orderId`.",
						"content": {
							"application/json": {
								"schema": {
									"anyOf": [
										{
											"$ref": "#/components/schemas/BuildTransactionsResponse"
										},
										{
											"$ref": "#/components/schemas/BuildDepositAddressResponse"
										}
									]
								},
								"example": {
									"orderId": "0x35dc8d390877c71baacadb4001eea0055804cfc306f599fbfc97c1d69d64d30a",
									"nonce": "48210338951092635551940726350418473090118563497023168275518271946413510239861",
									"approveTxs": [
										{
											"to": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
											"data": "0x095ea7b3000000000000000000000000b280c373f57c9169e009a66496ee556084afad240000000000000000000000000000000000000000000000000000000005f5e100",
											"value": "0",
											"chainId": 42161
										}
									],
									"depositTx": {
										"to": "0xb280C373F57c9169e009a66496EE556084afAd24",
										"from": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4",
										"data": "0xf3125a1f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000005f5e100",
										"value": "0x5af3107a4000",
										"chainId": 42161,
										"gasLimit": "0x3d090"
									}
								}
							}
						}
					},
					"400": {
						"description": "Invalid body (`ValidationError`), malformed JSON (`NamedError`), or a rejected request (`Error`): an unsupported token, an amount at or below the flat fee, a request edited after its quote, or a missing or invalid recipient.",
						"content": {
							"application/json": {
								"schema": {
									"anyOf": [
										{
											"$ref": "#/components/schemas/ValidationError"
										},
										{
											"$ref": "#/components/schemas/NamedError"
										},
										{
											"$ref": "#/components/schemas/Error"
										}
									]
								},
								"example": {
									"error": "Quoted terms do not match the signature — re-quote"
								}
							}
						}
					},
					"401": {
						"description": "The `X-API-Key` header is missing.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "X-API-Key required"
								}
							}
						}
					},
					"403": {
						"description": "The key is unknown or past its rotation window, or your integrator registry row is disabled or invalid. A `403` is always about your account: do not retry.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Unknown or inactive integrator"
								}
							}
						}
					},
					"404": {
						"description": "Source and destination are the same asset.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Source and destination resolve to the same mToken"
								}
							}
						}
					},
					"409": {
						"description": "The quote's attestation is older than five minutes. Re-quote; nothing was stored.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Quoted terms expired at 1787000000"
								}
							}
						}
					},
					"429": {
						"description": "Rate limited per integrator and per IP. No `Retry-After`; back off and retry.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/RateLimitError"
								},
								"example": {
									"errorCode": "RATE_LIMITED",
									"message": "Too many requests, please retry later"
								}
							}
						}
					},
					"500": {
						"description": "Server-side failure (`Error`) or an unhandled one (`NamedError`). Retry with a new build, then escalate.",
						"content": {
							"application/json": {
								"schema": {
									"anyOf": [
										{
											"$ref": "#/components/schemas/Error"
										},
										{
											"$ref": "#/components/schemas/NamedError"
										}
									]
								},
								"example": {
									"error": "Failed to persist pending order"
								}
							}
						}
					},
					"501": {
						"description": "This deployment cannot take deposits from the source chain. `detail.missing` names the missing setting.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								}
							}
						}
					},
					"502": {
						"description": "A chain read or dependent service failed. A deposit-address reservation or order record may remain. Do not fund a recovered order without confirming it with Khalani; back off and retry at most once, then contact Khalani with the x-request-id.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Failed to quote deposit relay fee"
								}
							}
						}
					},
					"503": {
						"description": "Temporarily unavailable: your terms could not be read, a price or fee configuration is missing, or no solver can serve the direction (`Error`), or the API is in maintenance (`NamedError` with `Retry-After`). The variants cannot be told apart reliably, so cap your retries.",
						"headers": {
							"Retry-After": {
								"description": "Seconds to wait. Sent only by the maintenance response.",
								"schema": {
									"type": "integer"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"anyOf": [
										{
											"$ref": "#/components/schemas/Error"
										},
										{
											"$ref": "#/components/schemas/NamedError"
										}
									]
								},
								"example": {
									"name": "MaintenanceException",
									"message": "SystemMaintenance"
								}
							}
						}
					}
				}
			}
		},
		"/v2/orders/{orderId}": {
			"get": {
				"operationId": "getOrder",
				"summary": "Get an order",
				"description": "One order with its full on-chain trail. Public: the `orderId` is the only credential, so keep it out of shared URLs,\nlogs and analytics.\n\nPoll every 10 to 15 seconds until `state` is `delivered` or `delivery_failed`. Keep polling through\n`withdrawn_on_hub`, which means hub settlement with delivery not yet fully recorded. Use a local timeout\nand retain the `orderId` to resume; a timeout means unconfirmed, not failed.",
				"tags": ["Orders"],
				"security": [],
				"parameters": [
					{
						"name": "orderId",
						"in": "path",
						"required": true,
						"description": "The `orderId` from `/v2/build`. Case-insensitive.",
						"schema": {
							"type": "string",
							"pattern": "^0x[0-9a-fA-F]{64}$"
						},
						"example": "0x35dc8d390877c71baacadb4001eea0055804cfc306f599fbfc97c1d69d64d30a"
					}
				],
				"responses": {
					"200": {
						"description": "The order.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Order"
								},
								"example": {
									"orderId": "0x35dc8d390877c71baacadb4001eea0055804cfc306f599fbfc97c1d69d64d30a",
									"integrator": "acme",
									"srcToken": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
									"dstToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
									"srcChainId": 42161,
									"dstChainId": 8453,
									"srcAmountSpoke": "100000000",
									"depositor": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4",
									"depositAddress": null,
									"payoutAddr": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4",
									"refundAddr": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4",
									"fullFee": "349850",
									"intentOutcomeRate": "999700000000000000",
									"state": "delivered",
									"deposit": {
										"tx": "0xa37fc5f866fdd03a6443129b95f5a328eba3a36b0c4d68c467849e846775a04d",
										"at": 1786999720
									},
									"deliver": {
										"payout": {
											"tx": "0x938eedc52713a24442d412eca2d8aae68c3df30fca154226113c438f82df5aa7",
											"amount": "99620254"
										},
										"refund": null,
										"at": 1786999810
									},
									"deliveryFailed": null,
									"traces": {
										"rootIntentId": "0x01cb37f4c5f512f757df0452b51e3fe8daefda8dfdd7e6d298d841ac54f7d18b",
										"publish": {
											"tx": "0xad257bdb68adfa6f6d2bf551f29edeeadc2c58bbbc1806ee42a741c2e36f1d07",
											"at": 1786999745
										},
										"withdraw": {
											"tx": "0x17c2da9cc8b27b31e95406d399f5468b2caddbd272afd102d148a9de5bb5dde5",
											"settledOutcome": "99620254",
											"refundSource": "0",
											"accruedFee": "329910",
											"at": 1786999790
										},
										"chainObservations": [
											{
												"seq": 0,
												"intentId": "0x01cb37f4c5f512f757df0452b51e3fe8daefda8dfdd7e6d298d841ac54f7d18b",
												"intentState": "Solved",
												"observedTx": "0x7de125b4300430bd1801e4d12a10f7e76b9400d2a13eddd207232f63cc546656",
												"at": 1786999770
											}
										]
									}
								}
							}
						}
					},
					"400": {
						"description": "`orderId` is not `0x` plus 64 hex.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ValidationError"
								}
							}
						}
					},
					"404": {
						"description": "No order with that `orderId`.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Order not found"
								}
							}
						}
					},
					"500": {
						"description": "Unhandled failure. Retry once, then escalate with the `x-request-id` response header.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/NamedError"
								},
								"example": {
									"message": "Internal Error",
									"name": "InternalErrorException"
								}
							}
						}
					}
				}
			}
		},
		"/v2/orders": {
			"get": {
				"operationId": "listOrders",
				"summary": "List your orders",
				"description": "Your orders, newest first by build time, always scoped to your key. `traces.chainObservations` is empty here; read the\nsingle order for its trail.\n\nThe cursor is a keyset: orders built after your first page do not appear on later pages. Poll the first page for new\norders, and keep the filters unchanged while paging.",
				"tags": ["Orders"],
				"security": [
					{
						"ApiKeyAuth": []
					}
				],
				"parameters": [
					{
						"name": "depositor",
						"in": "query",
						"required": false,
						"description": "Only orders from this depositor.",
						"schema": {
							"type": "string",
							"pattern": "^0x[0-9a-fA-F]{40}$"
						}
					},
					{
						"name": "from",
						"in": "query",
						"required": false,
						"description": "Only orders with this source token. Either TRON form matches.",
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "to",
						"in": "query",
						"required": false,
						"description": "Only orders with this destination token. Either TRON form matches.",
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "state",
						"in": "query",
						"required": false,
						"description": "Only orders in this state.",
						"schema": {
							"type": "string",
							"enum": [
								"pending_deposit",
								"deposited",
								"published",
								"partially_filled",
								"terminal_chain",
								"withdrawn_on_hub",
								"delivered",
								"delivery_failed"
							]
						},
						"example": "delivered"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"description": "`nextCursor` from the previous page. Keep the other filters unchanged while paging.",
						"schema": {
							"type": "string",
							"pattern": "^\\d+_0x[0-9a-fA-F]{64}$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"description": "Page size, clamped to 1–200. Default 50.",
						"schema": {
							"type": "string",
							"pattern": "^\\d+$"
						},
						"example": "20"
					}
				],
				"responses": {
					"200": {
						"description": "A page of orders.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/OrderList"
								},
								"example": {
									"orders": [
										{
											"orderId": "0x35dc8d390877c71baacadb4001eea0055804cfc306f599fbfc97c1d69d64d30a",
											"integrator": "acme",
											"srcToken": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
											"dstToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
											"srcChainId": 42161,
											"dstChainId": 8453,
											"srcAmountSpoke": "100000000",
											"depositor": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4",
											"depositAddress": null,
											"payoutAddr": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4",
											"refundAddr": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4",
											"fullFee": "349850",
											"intentOutcomeRate": "999700000000000000",
											"state": "delivered",
											"deposit": {
												"tx": "0xa37fc5f866fdd03a6443129b95f5a328eba3a36b0c4d68c467849e846775a04d",
												"at": 1786999720
											},
											"deliver": {
												"payout": {
													"tx": "0x938eedc52713a24442d412eca2d8aae68c3df30fca154226113c438f82df5aa7",
													"amount": "99620254"
												},
												"refund": null,
												"at": 1786999810
											},
											"deliveryFailed": null,
											"traces": {
												"rootIntentId": "0x01cb37f4c5f512f757df0452b51e3fe8daefda8dfdd7e6d298d841ac54f7d18b",
												"publish": {
													"tx": "0xad257bdb68adfa6f6d2bf551f29edeeadc2c58bbbc1806ee42a741c2e36f1d07",
													"at": 1786999745
												},
												"withdraw": {
													"tx": "0x17c2da9cc8b27b31e95406d399f5468b2caddbd272afd102d148a9de5bb5dde5",
													"settledOutcome": "99620254",
													"refundSource": "0",
													"accruedFee": "329910",
													"at": 1786999790
												},
												"chainObservations": []
											}
										}
									],
									"nextCursor": "1786999700_0x35dc8d390877c71baacadb4001eea0055804cfc306f599fbfc97c1d69d64d30a"
								}
							}
						}
					},
					"400": {
						"description": "Invalid query.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ValidationError"
								}
							}
						}
					},
					"401": {
						"description": "The `X-API-Key` header is missing.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "X-API-Key required"
								}
							}
						}
					},
					"403": {
						"description": "The key is unknown or past its rotation window. A `403` is always about your account: do not retry.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Unknown or inactive integrator"
								}
							}
						}
					},
					"500": {
						"description": "Unhandled failure. Retry once, then escalate with the `x-request-id` response header.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/NamedError"
								},
								"example": {
									"message": "Internal Error",
									"name": "InternalErrorException"
								}
							}
						}
					}
				}
			}
		},
		"/v2/orders/{orderId}/cancel": {
			"post": {
				"operationId": "cancelOrder",
				"summary": "Cancel an order",
				"description": "Relays an EOA depositor's signed cancel. Valid once the order is `published`. The filled part is paid out and the rest\nrefunded when the hub settles.\n\nA `200` is an acceptance, not settlement: keep polling the order. A cancel that races a fill is safe; whichever lands\nfirst settles the order. Sign a fresh `nonce` on every attempt.\n\nOnly ECDSA signatures recovering to the depositor or the delegate operator are accepted; ERC-1271 is not supported.\nA contract wallet's owner signature does not match the depositing contract. Wait for automatic settlement at expiry\nor contact Khalani for help cancelling early.",
				"tags": ["Orders"],
				"security": [
					{
						"ApiKeyAuth": []
					}
				],
				"parameters": [
					{
						"name": "orderId",
						"in": "path",
						"required": true,
						"description": "The `orderId` from `/v2/build`. Case-insensitive.",
						"schema": {
							"type": "string",
							"pattern": "^0x[0-9a-fA-F]{64}$"
						},
						"example": "0x35dc8d390877c71baacadb4001eea0055804cfc306f599fbfc97c1d69d64d30a"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"$ref": "#/components/schemas/CancelRequest"
							},
							"example": {
								"payload": {
									"nonce": "90193471235580291647163018827702615384561129844105227391950712038818471125043",
									"rootIntentId": "0x01cb37f4c5f512f757df0452b51e3fe8daefda8dfdd7e6d298d841ac54f7d18b"
								},
								"signature": "0x60ce0a47bc64e07a5437de5fd4e6008bce46756d4d7c971710283924888b2a137a91ed09461b5848bb2b7341f5c258da3f97853e73662275f047e0c3c20882211b"
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Accepted.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/CancelResponse"
								},
								"example": {
									"medusaSubmissionId": "0xd51bb36fd7ad3c3e0b2c7a7f29f04de6a6e2d2a1f5b1f0e9d9f0f9a6a1f5c7e3"
								}
							}
						}
					},
					"400": {
						"description": "Invalid body, or `rootIntentId` is not this order's.",
						"content": {
							"application/json": {
								"schema": {
									"anyOf": [
										{
											"$ref": "#/components/schemas/ValidationError"
										},
										{
											"$ref": "#/components/schemas/NamedError"
										},
										{
											"$ref": "#/components/schemas/Error"
										}
									]
								},
								"example": {
									"error": "Payload rootIntentId does not match the order's published root intent"
								}
							}
						}
					},
					"401": {
						"description": "The `X-API-Key` header is missing.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "X-API-Key required"
								}
							}
						}
					},
					"403": {
						"description": "The key is unknown or past its rotation window. A `403` is always about your account: do not retry.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Unknown or inactive integrator"
								}
							}
						}
					},
					"404": {
						"description": "No such order, or it belongs to another integrator.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Order not found"
								}
							}
						}
					},
					"409": {
						"description": "Not published yet, so there is nothing to cancel.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								},
								"example": {
									"error": "Order has not been published yet — wait for the deposit to clear or use stuck-deposit recovery."
								}
							}
						}
					},
					"500": {
						"description": "Unhandled failure. Retry once, then escalate with the `x-request-id` response header.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/NamedError"
								},
								"example": {
									"message": "Internal Error",
									"name": "InternalErrorException"
								}
							}
						}
					},
					"502": {
						"description": "The cancel was rejected or temporarily unavailable. Re-read the order and rejection. Fix a wrong signer or malformed signature before retrying; a fresh nonce does not fix either. For a reused nonce or temporary failure, retry with a fresh nonce only while the order is still open.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								}
							}
						}
					}
				}
			}
		},
		"/v2/health": {
			"get": {
				"operationId": "getHealth",
				"summary": "Service health",
				"description": "Global liveness of the order pipeline. Not your readiness: use `/v2/params` for that.",
				"tags": ["Service"],
				"security": [],
				"responses": {
					"200": {
						"description": "Healthy.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/HealthResponse"
								},
								"example": {
									"status": "ok",
									"counts": {
										"totalOrders": 1250,
										"pending": 3,
										"deposited": 1,
										"published": 4,
										"partiallyFilled": 1,
										"terminalChain": 0,
										"withdrawn": 12,
										"delivered": 1180,
										"deliveryFailed": 0,
										"stuck": 0,
										"abandoned": 49,
										"undelivered": 0
									},
									"lastBuildAt": 1786999700,
									"lastWithdrawnAt": 1786999790
								}
							}
						}
					},
					"500": {
						"description": "Unhandled failure. Retry once, then escalate with the `x-request-id` response header.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/NamedError"
								},
								"example": {
									"message": "Internal Error",
									"name": "InternalErrorException"
								}
							}
						}
					},
					"503": {
						"description": "The order store could not be read.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/HealthResponse"
								},
								"example": {
									"status": "degraded",
									"counts": null,
									"lastBuildAt": null,
									"lastWithdrawnAt": null
								}
							}
						}
					}
				}
			}
		}
	},
	"components": {
		"securitySchemes": {
			"ApiKeyAuth": {
				"type": "apiKey",
				"in": "header",
				"name": "X-API-Key",
				"description": "Your integrator API key. Backend only."
			}
		},
		"schemas": {
			"BuildDepositAddressResponse": {
				"type": "object",
				"properties": {
					"orderId": {
						"type": "string",
						"pattern": "^0x[0-9a-fA-F]{64}$",
						"description": "`keccak256(abi.encode(depositor, nonce))`, lowercase. Keys every later call: persist it."
					},
					"nonce": {
						"type": "string",
						"pattern": "^\\d+$",
						"description": "Decimal uint256 nonce of this deposit. Already part of `orderId` and the deposit."
					},
					"depositAddress": {
						"type": "string",
						"description": "Transfer the source token here, from any wallet."
					},
					"expectedAmount": {
						"type": "string",
						"pattern": "^\\d+$",
						"description": "The exact amount to transfer, in source base units. A transfer of any other amount is rejected."
					},
					"deadline": {
						"type": "integer",
						"minimum": 0,
						"description": "Intent publication expiry, in unix seconds. Budget time for source-chain confirmation and hub publication before this deadline. If insufficient time remains, rebuild before sending funds; a deposit that cannot publish before expiry requires operator recovery."
					}
				},
				"required": ["orderId", "nonce", "depositAddress", "expectedAmount", "deadline"],
				"description": "Build result for a non-EVM source chain (TRON): no transactions, a deposit address instead."
			},
			"BuildRequest": {
				"type": "object",
				"properties": {
					"srcToken": {
						"type": "object",
						"properties": {
							"chainId": {
								"type": "integer",
								"minimum": 0,
								"description": "Spoke chain id."
							},
							"token": {
								"description": "Spoke-token contract address. TRON accepts base58 or hex41.",
								"type": "string"
							}
						},
						"required": ["chainId", "token"],
						"description": "The token the depositor sends."
					},
					"dstToken": {
						"type": "object",
						"properties": {
							"chainId": {
								"type": "integer",
								"minimum": 0,
								"description": "Spoke chain id."
							},
							"token": {
								"description": "Spoke-token contract address. TRON accepts base58 or hex41.",
								"type": "string"
							}
						},
						"required": ["chainId", "token"],
						"description": "The token paid out."
					},
					"amount": {
						"type": "string",
						"pattern": "^[1-9]\\d*$",
						"description": "The deposit, in source base units."
					},
					"intentOutcomeRate": {
						"type": "string",
						"pattern": "^[1-9]\\d*$",
						"description": "The rate the order publishes at, 1e18-scaled, from `/v2/quote`. Used as sent."
					},
					"terms": {
						"description": "The quote's attestation, echoed unchanged. Always send it: without it the rate is signed as sent and the flat fee is recomputed at current config. Expired returns `409`; edited returns `400`.",
						"type": "object",
						"properties": {
							"flatFee": {
								"type": "string",
								"pattern": "^\\d+$"
							},
							"expiresAt": {
								"type": "string",
								"pattern": "^\\d+$"
							},
							"signature": {
								"type": "string",
								"pattern": "^0x[0-9a-fA-F]+$"
							}
						},
						"required": ["flatFee", "expiresAt", "signature"]
					},
					"depositor": {
						"description": "EVM address that signs and sends the deposit. Lowercase or exact EIP-55 checksum.",
						"type": "string",
						"pattern": "^0x[0-9a-fA-F]{40}$"
					},
					"payoutAddr": {
						"description": "Receives the payout on the destination chain. Defaults to `depositor`; use the default only if the user controls that address on the destination chain. Contract-wallet depositors must pass an explicit recipient. Required when the destination is non-EVM (TRON).",
						"type": "string"
					},
					"refundAddr": {
						"description": "Receives any refund on the source chain. Defaults to `depositor`; use the default only if the user controls that address on the source chain. Contract-wallet depositors must pass an explicit recipient. Required when the source is non-EVM (TRON).",
						"type": "string"
					}
				},
				"required": ["srcToken", "dstToken", "amount", "intentOutcomeRate", "depositor"],
				"description": "`quote.build` from `/v2/quote`, plus `depositor` and any recipients."
			},
			"BuildTransactionsResponse": {
				"type": "object",
				"properties": {
					"orderId": {
						"type": "string",
						"pattern": "^0x[0-9a-fA-F]{64}$",
						"description": "`keccak256(abi.encode(depositor, nonce))`, lowercase. Keys every later call: persist it."
					},
					"nonce": {
						"type": "string",
						"pattern": "^\\d+$",
						"description": "Decimal uint256 nonce of this deposit. Already part of `orderId` and the deposit."
					},
					"approveTxs": {
						"description": "Present only when the depositor's allowance is too low. Send each in order and wait for it to confirm before `depositTx`. A leading `approve(0)` appears only when a residual allowance must be reset.",
						"type": "array",
						"items": {
							"type": "object",
							"properties": {
								"to": {
									"type": "string",
									"pattern": "^0x[0-9a-fA-F]{40}$",
									"description": "The source token contract."
								},
								"data": {
									"type": "string",
									"pattern": "^0x[0-9a-fA-F]*$"
								},
								"value": {
									"type": "string",
									"pattern": "^\\d+$",
									"description": "Decimal wei; always `0`."
								},
								"chainId": {
									"type": "integer",
									"minimum": 0,
									"description": "Spoke chain id."
								}
							},
							"required": ["to", "data", "value", "chainId"]
						}
					},
					"depositTx": {
						"type": "object",
						"properties": {
							"to": {
								"type": "string",
								"pattern": "^0x[0-9a-fA-F]{40}$",
								"description": "The source chain's deposit contract."
							},
							"from": {
								"type": "string",
								"pattern": "^0x[0-9a-fA-F]{40}$",
								"description": "Equals `depositor`. A deposit sent from any other account strands the funds."
							},
							"data": {
								"type": "string",
								"pattern": "^0x[0-9a-fA-F]*$"
							},
							"value": {
								"type": "string",
								"pattern": "^0x[0-9a-fA-F]*$",
								"description": "Hex wei: the relay fee, sent as the transaction value."
							},
							"chainId": {
								"type": "integer",
								"minimum": 0,
								"description": "Spoke chain id."
							},
							"gasLimit": {
								"type": "string",
								"pattern": "^0x[0-9a-fA-F]*$",
								"description": "Hex gas limit; a fixed value, not an estimate."
							}
						},
						"required": ["to", "from", "data", "value", "chainId", "gasLimit"],
						"description": "The deposit, unsigned. Send it exactly once, from `depositor`, after any `approveTxs`."
					}
				},
				"required": ["orderId", "nonce", "depositTx"],
				"description": "Build result for an EVM source chain: the transactions for the depositor's wallet to send."
			},
			"CancelRequest": {
				"type": "object",
				"properties": {
					"payload": {
						"type": "object",
						"properties": {
							"nonce": {
								"type": "string",
								"pattern": "^\\d+$",
								"description": "A fresh random uint256 per cancel attempt, decimal. Not the build nonce; a reused value is rejected."
							},
							"rootIntentId": {
								"type": "string",
								"pattern": "^0x[0-9a-fA-F]{64}$",
								"description": "The order's `traces.rootIntentId`."
							}
						},
						"required": ["nonce", "rootIntentId"]
					},
					"signature": {
						"type": "string",
						"pattern": "^0x[0-9a-fA-F]+$",
						"description": "The depositor's EIP-712 `OrderDelegateV2Cancel` signature over `payload`."
					}
				},
				"required": ["payload", "signature"],
				"description": "A depositor-signed cancel, relayed by your backend."
			},
			"CancelResponse": {
				"type": "object",
				"properties": {
					"medusaSubmissionId": {
						"type": "string",
						"description": "Identifier of the accepted cancel submission."
					}
				},
				"required": ["medusaSubmissionId"],
				"description": "The cancel was accepted, not yet settled. Poll the order until `delivered` or `delivery_failed`, with a local timeout."
			},
			"Error": {
				"type": "object",
				"properties": {
					"error": {
						"type": "string"
					},
					"detail": {
						"type": "object",
						"properties": {
							"minSrcAmount": {
								"description": "Smallest deposit that would quote, in source base units.",
								"type": "string",
								"pattern": "^\\d+$"
							},
							"maxSrcAmount": {
								"description": "Largest deposit that would quote, in source base units.",
								"type": "string",
								"pattern": "^\\d+$"
							},
							"maxOutcomeAmount": {
								"description": "Largest output that would quote, in destination base units.",
								"type": "string",
								"pattern": "^\\d+$"
							},
							"missing": {
								"description": "The deployment setting this direction needs.",
								"type": "string"
							}
						}
					}
				},
				"required": ["error"],
				"description": "An error raised by the route itself."
			},
			"HealthResponse": {
				"type": "object",
				"properties": {
					"status": {
						"type": "string",
						"enum": ["ok", "degraded"],
						"description": "`degraded` when the order store could not be read. The response is then a `503` with `counts: null`."
					},
					"counts": {
						"anyOf": [
							{
								"type": "object",
								"properties": {
									"totalOrders": {
										"type": "integer",
										"description": "Every order ever built."
									},
									"pending": {
										"type": "integer",
										"description": "`pending_deposit` orders still inside their deposit window."
									},
									"deposited": {
										"type": "integer"
									},
									"published": {
										"type": "integer"
									},
									"partiallyFilled": {
										"type": "integer"
									},
									"terminalChain": {
										"type": "integer"
									},
									"withdrawn": {
										"type": "integer",
										"description": "`withdrawn_on_hub`: settled, delivery not yet fully recorded."
									},
									"delivered": {
										"type": "integer"
									},
									"deliveryFailed": {
										"type": "integer"
									},
									"stuck": {
										"type": "integer",
										"description": "Mid-flight orders that automated recovery has handed to an operator."
									},
									"abandoned": {
										"type": "integer",
										"description": "Orders whose deposit never arrived before expiry. No funds moved."
									},
									"undelivered": {
										"type": "integer",
										"description": "Settled 12h+ ago with a payout or refund leg still unrecorded. Counted inside `withdrawn`, not beside it."
									}
								},
								"required": [
									"totalOrders",
									"pending",
									"deposited",
									"published",
									"partiallyFilled",
									"terminalChain",
									"withdrawn",
									"delivered",
									"deliveryFailed",
									"stuck",
									"abandoned",
									"undelivered"
								]
							},
							{
								"type": "null"
							}
						],
						"description": "Order counts across all integrators. `null` when `status` is `degraded`."
					},
					"lastBuildAt": {
						"anyOf": [
							{
								"type": "integer",
								"minimum": 0
							},
							{
								"type": "null"
							}
						]
					},
					"lastWithdrawnAt": {
						"anyOf": [
							{
								"type": "integer",
								"minimum": 0
							},
							{
								"type": "null"
							}
						]
					}
				},
				"required": ["status", "counts", "lastBuildAt", "lastWithdrawnAt"],
				"description": "Liveness of the order pipeline, global across integrators."
			},
			"NamedError": {
				"type": "object",
				"properties": {
					"message": {
						"type": "string"
					},
					"name": {
						"type": "string",
						"description": "`MaintenanceException` (503), `BadRequestException` (malformed JSON) or `InternalErrorException` (500)."
					}
				},
				"required": ["message", "name"],
				"description": "Maintenance, a malformed JSON body, or an unhandled failure. Carries `message`, not `error`."
			},
			"Order": {
				"type": "object",
				"properties": {
					"orderId": {
						"type": "string",
						"pattern": "^0x[0-9a-fA-F]{64}$",
						"description": "`keccak256(abi.encode(depositor, nonce))`, lowercase. Keys every later call: persist it."
					},
					"integrator": {
						"type": "string",
						"description": "Your integrator name."
					},
					"srcToken": {
						"type": "string",
						"description": "Address in the chain's native display form: EVM `0x` hex, TRON base58."
					},
					"dstToken": {
						"type": "string",
						"description": "Address in the chain's native display form: EVM `0x` hex, TRON base58."
					},
					"srcChainId": {
						"anyOf": [
							{
								"type": "integer",
								"minimum": 0,
								"description": "Spoke chain id."
							},
							{
								"type": "null"
							}
						]
					},
					"dstChainId": {
						"anyOf": [
							{
								"type": "integer",
								"minimum": 0,
								"description": "Spoke chain id."
							},
							{
								"type": "null"
							}
						]
					},
					"srcAmountSpoke": {
						"type": "string",
						"pattern": "^\\d+$",
						"description": "The deposit, in source base units."
					},
					"depositor": {
						"type": "string",
						"pattern": "^0x[0-9a-fA-F]{40}$",
						"description": "Lowercase. Compare addresses case-insensitively across endpoints."
					},
					"depositAddress": {
						"anyOf": [
							{
								"type": "string",
								"description": "Address in the chain's native display form: EVM `0x` hex, TRON base58."
							},
							{
								"type": "null"
							}
						],
						"description": "Non-EVM source only: the address `/v2/build` handed out. `null` on an EVM source."
					},
					"payoutAddr": {
						"type": "string",
						"description": "Address in the chain's native display form: EVM `0x` hex, TRON base58."
					},
					"refundAddr": {
						"type": "string",
						"description": "Address in the chain's native display form: EVM `0x` hex, TRON base58."
					},
					"fullFee": {
						"anyOf": [
							{
								"type": "string",
								"pattern": "^\\d+$"
							},
							{
								"type": "null"
							}
						],
						"description": "Everything withheld from the deposit at publish (flat fee, Khalani's bps and your commission), in source base units. `null` until published."
					},
					"intentOutcomeRate": {
						"anyOf": [
							{
								"type": "string",
								"pattern": "^\\d+$"
							},
							{
								"type": "null"
							}
						],
						"description": "The rate this order published at, 1e18-scaled."
					},
					"state": {
						"type": "string",
						"enum": [
							"pending_deposit",
							"deposited",
							"published",
							"partially_filled",
							"terminal_chain",
							"withdrawn_on_hub",
							"delivered",
							"delivery_failed"
						],
						"description": "Closed set. Poll until `delivered` or `delivery_failed`; `withdrawn_on_hub` means hub settlement with delivery not yet fully recorded. Use a local timeout and resume by orderId if the result remains unconfirmed."
					},
					"deposit": {
						"anyOf": [
							{
								"type": "object",
								"properties": {
									"tx": {
										"type": "string",
										"description": "Transaction hash (EVM) or transaction id (TRON)."
									},
									"at": {
										"type": "integer",
										"minimum": 0,
										"description": "When it was observed, unix seconds."
									}
								},
								"required": ["tx", "at"]
							},
							{
								"type": "null"
							}
						],
						"description": "The source-chain deposit. Stays `null` on a non-EVM source."
					},
					"deliver": {
						"anyOf": [
							{
								"type": "object",
								"properties": {
									"payout": {
										"anyOf": [
											{
												"type": "object",
												"properties": {
													"tx": {
														"type": "string"
													},
													"amount": {
														"anyOf": [
															{
																"type": "string",
																"pattern": "^\\d+$"
															},
															{
																"type": "null"
															}
														],
														"description": "Mirrors `traces.withdraw`; `null` until that is enriched."
													}
												},
												"required": ["tx", "amount"]
											},
											{
												"type": "null"
											}
										],
										"description": "Payout to `payoutAddr` on the destination chain; `null` until recorded."
									},
									"refund": {
										"anyOf": [
											{
												"type": "object",
												"properties": {
													"tx": {
														"type": "string"
													},
													"amount": {
														"anyOf": [
															{
																"type": "string",
																"pattern": "^\\d+$"
															},
															{
																"type": "null"
															}
														],
														"description": "Mirrors `traces.withdraw`; `null` until that is enriched."
													}
												},
												"required": ["tx", "amount"]
											},
											{
												"type": "null"
											}
										],
										"description": "Refund to `refundAddr` on the source chain; `null` until recorded."
									},
									"at": {
										"type": "integer",
										"minimum": 0,
										"description": "When the last recorded leg landed."
									}
								},
								"required": ["payout", "refund", "at"]
							},
							{
								"type": "null"
							}
						],
						"description": "Delivery of the settlement's legs. Best-effort: non-null once either leg is recorded."
					},
					"deliveryFailed": {
						"anyOf": [
							{
								"type": "object",
								"properties": {
									"msg": {
										"type": "string",
										"enum": ["payout failed", "refund failed", "payout and refund both failed"]
									},
									"payout": {
										"anyOf": [
											{
												"type": "string"
											},
											{
												"type": "null"
											}
										],
										"description": "The transport's report for the payout leg."
									},
									"refund": {
										"anyOf": [
											{
												"type": "string"
											},
											{
												"type": "null"
											}
										],
										"description": "The transport's report for the refund leg."
									}
								},
								"required": ["msg", "payout", "refund"]
							},
							{
								"type": "null"
							}
						],
						"description": "Set with state `delivery_failed`: which leg is undeliverable. Escalate with the `orderId`."
					},
					"traces": {
						"type": "object",
						"properties": {
							"rootIntentId": {
								"anyOf": [
									{
										"type": "string",
										"pattern": "^0x[0-9a-fA-F]{64}$"
									},
									{
										"type": "null"
									}
								],
								"description": "The published intent. Sign cancels against it. `null` until published."
							},
							"publish": {
								"anyOf": [
									{
										"type": "object",
										"properties": {
											"tx": {
												"type": "string",
												"description": "Transaction hash (EVM) or transaction id (TRON)."
											},
											"at": {
												"type": "integer",
												"minimum": 0,
												"description": "When it was observed, unix seconds."
											}
										},
										"required": ["tx", "at"]
									},
									{
										"type": "null"
									}
								]
							},
							"withdraw": {
								"anyOf": [
									{
										"type": "object",
										"properties": {
											"tx": {
												"type": "string"
											},
											"settledOutcome": {
												"anyOf": [
													{
														"type": "string",
														"pattern": "^\\d+$"
													},
													{
														"type": "null"
													}
												],
												"description": "Paid out, in destination base units."
											},
											"refundSource": {
												"anyOf": [
													{
														"type": "string",
														"pattern": "^\\d+$"
													},
													{
														"type": "null"
													}
												],
												"description": "Refunded, in source base units."
											},
											"accruedFee": {
												"anyOf": [
													{
														"type": "string",
														"pattern": "^\\d+$"
													},
													{
														"type": "null"
													}
												],
												"description": "Fee kept: the flat fee plus Khalani's bps on the filled part, in source base units."
											},
											"at": {
												"type": "integer",
												"minimum": 0
											}
										},
										"required": ["tx", "settledOutcome", "refundSource", "accruedFee", "at"]
									},
									{
										"type": "null"
									}
								],
								"description": "Settlement on the hub. Amounts are `null` briefly after it appears; re-poll."
							},
							"chainObservations": {
								"type": "array",
								"items": {
									"type": "object",
									"properties": {
										"seq": {
											"type": "integer"
										},
										"intentId": {
											"type": "string",
											"pattern": "^0x[0-9a-fA-F]{64}$"
										},
										"intentState": {
											"type": "string",
											"enum": ["Open", "Solved", "Cancelled"]
										},
										"observedTx": {
											"type": "string"
										},
										"at": {
											"type": "integer",
											"minimum": 0
										}
									},
									"required": ["seq", "intentId", "intentState", "observedTx", "at"]
								},
								"description": "Ordered trail of the intent and its fills. Always empty in the order list."
							}
						},
						"required": ["rootIntentId", "publish", "withdraw", "chainObservations"],
						"description": "Diagnostics. Track `state`, `deposit` and `deliver` instead."
					}
				},
				"required": [
					"orderId",
					"integrator",
					"srcToken",
					"dstToken",
					"srcChainId",
					"dstChainId",
					"srcAmountSpoke",
					"depositor",
					"depositAddress",
					"payoutAddr",
					"refundAddr",
					"fullFee",
					"intentOutcomeRate",
					"state",
					"deposit",
					"deliver",
					"deliveryFailed",
					"traces"
				],
				"description": "One order and its lifecycle. Nested objects are `null` until their event is observed."
			},
			"OrderList": {
				"type": "object",
				"properties": {
					"orders": {
						"type": "array",
						"items": {
							"$ref": "#/components/schemas/Order"
						},
						"description": "Newest first by build time."
					},
					"nextCursor": {
						"anyOf": [
							{
								"type": "string"
							},
							{
								"type": "null"
							}
						],
						"description": "Pass as `cursor` for the next page. Non-null on every non-empty page: stop when `orders` comes back empty."
					}
				},
				"required": ["orders", "nextCursor"],
				"description": "A page of your orders."
			},
			"ParamsResponse": {
				"type": "object",
				"properties": {
					"tokens": {
						"type": "array",
						"items": {
							"type": "object",
							"properties": {
								"chainId": {
									"type": "integer",
									"minimum": 0,
									"description": "Spoke chain id."
								},
								"token": {
									"type": "string",
									"description": "Address in the chain's native display form: EVM `0x` hex, TRON base58."
								},
								"symbol": {
									"type": "string"
								},
								"decimals": {
									"type": "integer",
									"minimum": 0,
									"description": "Decimals of this token on this chain. They vary per chain."
								},
								"depositFee": {
									"type": "string",
									"pattern": "^\\d+$",
									"description": "Fixed fee when this token is the source, in its own base units. Charged even if the order never fills."
								},
								"withdrawFee": {
									"type": "string",
									"pattern": "^\\d+$",
									"description": "Fixed fee when this token is the destination, in its own base units."
								}
							},
							"required": ["chainId", "token", "symbol", "decimals", "depositFee", "withdrawFee"]
						},
						"description": "Every token you can trade. Any listed token can be traded against any other. A token with no configured fee is omitted."
					},
					"terms": {
						"type": "object",
						"properties": {
							"operatorBps": {
								"type": "integer",
								"minimum": 0,
								"description": "Khalani's fee, in basis points of the amount left after the flat fee."
							},
							"commissionBps": {
								"type": "integer",
								"minimum": 0,
								"description": "Your commission, in basis points of the same amount."
							},
							"commissionWallet": {
								"type": "string",
								"pattern": "^0x[0-9a-fA-F]{40}$",
								"description": "Hub address your commission is paid to on settlement. The zero address if none is set."
							},
							"orderTtl": {
								"type": "integer",
								"minimum": 0,
								"description": "Seconds from `/v2/build` until the order's deadline. The clock starts at build, not at deposit. An API setting each build signs into its order."
							}
						},
						"required": ["operatorBps", "commissionBps", "commissionWallet", "orderTtl"],
						"description": "Your terms. The bps and the commission wallet come from the on-chain integrator registry the hub reads at publish; `orderTtl` is an API setting."
					}
				},
				"required": ["tokens", "terms"],
				"description": "The tokens you can trade, each with its fixed fees, and your commercial terms."
			},
			"QuoteResponse": {
				"type": "object",
				"properties": {
					"spend": {
						"type": "object",
						"properties": {
							"chainId": {
								"type": "integer",
								"minimum": 0,
								"description": "Spoke chain id."
							},
							"token": {
								"type": "string",
								"description": "Address in the chain's native display form: EVM `0x` hex, TRON base58."
							},
							"symbol": {
								"type": "string"
							},
							"decimals": {
								"type": "integer",
								"minimum": 0
							},
							"amount": {
								"type": "string",
								"pattern": "^\\d+$"
							}
						},
						"required": ["chainId", "token", "symbol", "decimals", "amount"],
						"description": "What the depositor sends, in source base units. Includes every fee."
					},
					"receive": {
						"type": "object",
						"properties": {
							"chainId": {
								"type": "integer",
								"minimum": 0,
								"description": "Spoke chain id."
							},
							"token": {
								"type": "string",
								"description": "Address in the chain's native display form: EVM `0x` hex, TRON base58."
							},
							"symbol": {
								"type": "string"
							},
							"decimals": {
								"type": "integer",
								"minimum": 0
							},
							"amount": {
								"type": "string",
								"pattern": "^\\d+$"
							}
						},
						"required": ["chainId", "token", "symbol", "decimals", "amount"],
						"description": "What the depositor receives if the order fills completely, in destination base units. Truncated, never rounded up."
					},
					"details": {
						"type": "object",
						"properties": {
							"intentOutcomeRate": {
								"type": "string",
								"pattern": "^\\d+$",
								"description": "The solver's rate, 1e18-scaled: destination per source unit of the published amount (after fees), not of the deposit. Not a token amount."
							},
							"protocolFee": {
								"type": "string",
								"pattern": "^\\d+$",
								"description": "The flat fee plus Khalani's bps, in source base units. Your commission is not included."
							}
						},
						"required": ["intentOutcomeRate", "protocolFee"]
					},
					"build": {
						"type": "object",
						"properties": {
							"srcToken": {
								"type": "object",
								"properties": {
									"chainId": {
										"type": "integer",
										"minimum": 0,
										"description": "Spoke chain id."
									},
									"token": {
										"type": "string",
										"description": "Address in the chain's native display form: EVM `0x` hex, TRON base58."
									}
								},
								"required": ["chainId", "token"]
							},
							"dstToken": {
								"type": "object",
								"properties": {
									"chainId": {
										"type": "integer",
										"minimum": 0,
										"description": "Spoke chain id."
									},
									"token": {
										"type": "string",
										"description": "Address in the chain's native display form: EVM `0x` hex, TRON base58."
									}
								},
								"required": ["chainId", "token"]
							},
							"amount": {
								"type": "string",
								"pattern": "^\\d+$",
								"description": "The deposit, in source base units."
							},
							"intentOutcomeRate": {
								"type": "string",
								"pattern": "^\\d+$",
								"description": "The rate the order will publish at, 1e18-scaled."
							},
							"terms": {
								"type": "object",
								"properties": {
									"flatFee": {
										"type": "string",
										"pattern": "^\\d+$",
										"description": "Flat fee in 18-decimal hub units. Signed over, so echo it unchanged."
									},
									"expiresAt": {
										"type": "string",
										"pattern": "^\\d+$",
										"description": "Unix seconds. The attestation is valid for five minutes."
									},
									"signature": {
										"type": "string",
										"pattern": "^0x[0-9a-fA-F]*$",
										"description": "Khalani's EIP-712 attestation over the quoted trade."
									}
								},
								"required": ["flatFee", "expiresAt", "signature"],
								"description": "Attestation that pins `/v2/build` to this quote. Always send it back."
							}
						},
						"required": ["srcToken", "dstToken", "amount", "intentOutcomeRate", "terms"],
						"description": "The `/v2/build` request, already assembled. Send it back with `depositor` (and recipients where required) added."
					}
				},
				"required": ["spend", "receive", "details", "build"],
				"description": "A price for one direction and size. A `200` means the amount is fillable now. Nothing is stored."
			},
			"RateLimitError": {
				"type": "object",
				"properties": {
					"errorCode": {
						"type": "string",
						"const": "RATE_LIMITED"
					},
					"message": {
						"type": "string"
					}
				},
				"required": ["errorCode", "message"],
				"description": "Rate limited. No `Retry-After`; back off and retry."
			},
			"ValidationError": {
				"type": "object",
				"properties": {
					"message": {
						"type": "string",
						"const": "Validation failed"
					},
					"name": {
						"type": "string",
						"const": "ValidationException"
					},
					"details": {
						"type": "array",
						"items": {
							"type": "object",
							"properties": {
								"field": {
									"type": "string"
								},
								"message": {
									"type": "string"
								},
								"code": {
									"type": "string"
								}
							},
							"required": ["field", "message", "code"]
						}
					}
				},
				"required": ["message", "name", "details"],
				"description": "The request failed schema validation. Carries `message`, not `error`."
			}
		}
	}
}
