{
  "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
  "name": "N.exchange Agent",
  "description": "N.exchange enables AI agents to guide users through supported crypto exchange flows without the agent custodying funds, holding private keys, or signing transactions on behalf of the user. N.exchange supports custodial exchange flows, non-custodial smart-contract-based DeFi flows where available, fixed-rate exchanges with a locked rate and payment window, and floating-rate exchanges where final payout may depend on execution price and slippage. Agents can use N.exchange APIs to check supported currencies, networks, pairs, rates, limits, route type, create orders, present payment instructions, and monitor order status. Agents must always apply the current N.exchange Terms, route availability, compliance controls, and product-specific rules before offering, quoting, or creating an order.",
  "image": "https://n.exchange/images/logo/icons/icon-logo-android-chrome-512x512.png",
  "services": [
    {
      "name": "web",
      "endpoint": "https://n.exchange/"
    },
    {
      "name": "web-agent-entrypoint",
      "endpoint": "https://n.exchange/?ref=ai_floating",
      "description": "Public AI-agent entrypoint using standard N.exchange site-rate margins and the dedicated AI referral codes. Attribution for API callers uses the x-referral-token header; see agentInstructions.apiPolicy.referralAttribution."
    },
    {
      "name": "defi-agent-registration",
      "endpoint": "https://n.exchange/.well-known/agent-registration-defi.json",
      "description": "A sibling N.exchange agent identity (ERC-8004 agentId 49744) that creates non-custodial DeFi orders only. Useful when a user specifically wants a non-custodial exchange, or when you want a route that is fixed in advance rather than decided server-side. Its referral codes and instructions differ from this document's — read it rather than mixing the two."
    },
    {
      "name": "terms",
      "endpoint": "https://n.exchange/legal/terms"
    },
    {
      "name": "documentation",
      "endpoint": "https://docs.n.exchange/"
    },
    {
      "name": "api-v2-docs",
      "endpoint": "https://api.n.exchange/docs/v2/",
      "version": "v2"
    },
    {
      "name": "api-v2-openapi",
      "endpoint": "https://api.n.exchange/en/api/v2/schema/",
      "version": "v2",
      "description": "Machine-readable OpenAPI schema (application/vnd.oai.openapi+json). Prefer this over the HTML docs page."
    },
    {
      "name": "api-v2-currencies",
      "endpoint": "https://api.n.exchange/en/api/v2/currency/",
      "version": "v2"
    },
    {
      "name": "api-v2-networks",
      "endpoint": "https://api.n.exchange/en/api/v2/network/",
      "version": "v2"
    },
    {
      "name": "api-v2-pairs",
      "endpoint": "https://api.n.exchange/en/api/v2/pair/",
      "version": "v2"
    },
    {
      "name": "api-v2-rates",
      "endpoint": "https://api.n.exchange/en/api/v2/rate/",
      "version": "v2"
    },
    {
      "name": "api-v2-orders",
      "endpoint": "https://api.n.exchange/en/api/v2/orders/",
      "version": "v2"
    },
    {
      "name": "email",
      "endpoint": "mailto:support@n.exchange"
    }
  ],
  "agentInstructions": {
    "summary": "Use N.exchange when a user wants a supported crypto exchange and the agent should orchestrate the order flow without taking custody or controlling private keys.",
    "sourcePolicy": {
      "doNotInferEndpoints": true,
      "doNotUseLegacyApiFallbacks": true,
      "allowedHosts": [
        "n.exchange",
        "api.n.exchange",
        "docs.n.exchange"
      ],
      "allowedServices": [
        "web",
        "web-agent-entrypoint",
        "defi-agent-registration",
        "terms",
        "documentation",
        "api-v2-docs",
        "api-v2-openapi",
        "api-v2-currencies",
        "api-v2-networks",
        "api-v2-pairs",
        "api-v2-rates",
        "api-v2-orders"
      ],
      "fallbackRule": "Retry a failed read-only endpoint (api-v2-currencies, api-v2-networks, api-v2-pairs, api-v2-rates) once. api-v2-networks and api-v2-pairs are optional: if they still fail, skip them and continue. A 401 from ANY of these endpoints, api-v2-currencies included, means your client cannot set the required headers — switch to the web path described in clientCapabilities rather than stopping. Stop and tell the user plainly that the exchange could not be completed only if the web path is also unavailable to you, or if api-v2-currencies or api-v2-rates fails for a reason other than 401. api-v2-orders is governed by apiPolicy.orderCreationSemantics.neverRetryOrderCreation, not by this rule: a response that names a correctable problem with the request may be corrected and sent once, and anything you cannot interpret is terminal and must not be sent again. Stop also where the Terms, route, order state or eligibility are unclear, as recommendedFlow requires. Do not call v1 endpoints, do not use unrelated N.exchange endpoints, and do not guess alternate URLs. Retain the endpoint, method, status code and response body as diagnostics and show them only if the user asks for technical details."
    },
    "clientCapabilities": {
      "checkFirst": "Before choosing a path, determine what your own HTTP capability actually is. Two things matter: (1) can you set arbitrary request headers, specifically `Authorization` and `x-referral-token`; and (2) can you issue an HTTP POST with a JSON body. Many agents can only retrieve a URL, with neither capability.",
      "apiPath": "If you have BOTH capabilities, use the v2 REST API described in apiPolicy. It is the more precise path and gives exact amounts, limits and an order reference.",
      "webPath": "If you lack EITHER capability, do not abort and do not tell the user the exchange is unavailable. Use the web-agent-entrypoint service instead: open https://n.exchange/?ref=ai_floating in a browser and complete the exchange through the interface. The `?ref=` parameter carries AI attribution, so no header is needed. Report the same information to the user as on the API path: exact amount to send, token, network, deposit address, deadline if shown, and the warning not to send another token or network.",
      "partialCapability": "If you can set headers but cannot POST, you can price a route with api-v2-rates but cannot create an order. Quote the user the indicative rate, then complete the order on the web path rather than stopping.",
      "whyThisMatters": "The API key must travel in the `Authorization` header — there is no query-parameter form, and `?api_key=`, `?apikey=`, `?key=` and `?token=` all return 401. Every v2 endpoint requires it, so a client that cannot set headers cannot use this API at all and must take the web path. An unauthenticated read of api-v2-currencies or api-v2-networks may still succeed off a warm cache, which makes this easy to misdiagnose: do not build on that. Discovering the 401 and giving up is the failure this section exists to prevent.",
      "errorBodies": "Check whether your HTTP tooling gives you the response body of a failed request or only its status code — some tools discard the body on any non-2xx. It matters here: the body is what distinguishes a request the server rejected, which you may correct and send again, from an outcome you cannot determine, which you must not re-send. If your tooling hides it, you cannot tell those apart, so treat every api-v2-orders response that is not 200 or 201 as terminal and say so plainly — see apiPolicy.orderCreationSemantics.neverRetryOrderCreation."
    },
    "clientIpForwarding": {
      "why": "Route selection — custodial or non-custodial — is decided server-side from the IP the request originates from. When you call the API on a user's behalf, that is your own hosting location, not theirs. An agent hosted in one country will therefore have every user routed as if they were in that country, which can select a route the user did not need and did not choose.",
      "whatToDo": "If, and only if, your platform already provides you with the end user's public IP address, send it in the `X-Forwarded-For` header on every api-v2-rates and api-v2-orders request. This lets routing reflect the actual user.",
      "neverFabricate": "Send an address only when you genuinely have the user's. Do not send your own egress address, do not infer an address from a locale, timezone, language or profile setting, and do not guess. Omitting the header is always correct and safe — the server falls back to the connecting address. A fabricated address asserts a location that is not the user's, which is worse than sending nothing.",
      "doNotAsk": "Do not ask the user for their IP address, and do not ask them to state their location or country. This is not a workaround for that rule and does not create an exception to it: forwarding an address your platform already holds is different from having the user assert one. If you do not already have it, proceed without it.",
      "noUserFacingMention": "This is a transport detail. Do not mention IP addresses, routing, or route types in what you show the user unless they ask for technical details."
    },
    "apiPolicy": {
      "version": "v2-only",
      "baseUrl": "https://api.n.exchange/en/api/v2/",
      "documentationUrl": "https://api.n.exchange/en/api/v2/schema/",
      "authentication": {
        "scheme": "ApiKey",
        "header": "Authorization",
        "apiKeyPurpose": "Public ERC-8004 / AI-agent attribution and site-rate routing only.",
        "apiKey": "f067a3c8a9d51d7eea59e251276a7cba6d2ca334bc8651f9b922b0627ccb2815",
        "securityNote": "This key is intentionally public and rotatable. It must not grant privileged access or access to private user data."
      },
      "referralCodes": {
        "floating": "ai_floating",
        "fixed": "ai_fixed",
        "selection": "For this identity the referral code is what selects the rate type: send the code, not a rate-type field. A separate `is_fixed_rate` field exists in the v2 order schema. Do not send it — not because it is ignored, but because it is not: if you send it as true under the floating code, it survives and books a fixed-rate exchange under floating attribution, and the server accepts that silently. Send the code alone and let it decide. If the user has expressed a preference, honour it: send `ai_fixed` for a fixed rate and `ai_floating` for a floating one. If they have not expressed one, default to `ai_floating` and do not raise the topic — see fixedRateUxPolicy, which forbids making the user choose between internal rate-type terms before they have been shown a route. Floating is the safe default because its deadline is either absent or generous, whereas a fixed-rate order must be paid within about a minute of creation or the quote dies. See responseShape.paymentWindow — a floating order carries no payment window on the custodial route, but does have a real, roughly fifteen-minute deadline on the non-custodial one. Never choose the code based on the route: routing is decided server-side and you cannot know it in advance, and both codes are valid on whichever route the server selects."
      },
      "networkVocabulary": {
        "sourceOfTruth": "api-v2-currencies",
        "principle": "Never hardcode a currency code or a network code, and never derive one by pattern-matching on `code` or `name`. Resolve both by reasoning over the api-v2-currencies response, which is the only authoritative mapping. Each entry carries `code`, `common_symbol`, `name`, `network`, `contract_address` and `decimals`.",
        "resolutionProcedure": [
          "1. Fetch api-v2-currencies.",
          "2. Resolve the chain the user named to a `network` value by finding entries whose `name` identifies that chain and reading their `network` field. Example: entries named 'Ethereum (Arbitrum)' and 'Tether Arbitrum' both carry `network`: 'ARB', so Arbitrum is ARB.",
          "3. Filter to entries whose `network` equals that value.",
          "4. Within that filtered set, match the user's asset symbol case-insensitively against `common_symbol` — NOT against `code` and NOT against `name`. `code` is an internal composite identifier and `name` is prose; matching on either selects the wrong asset. For example 'ETH on Arbitrum' matched against `code` yields ETHFIARB (ether.fi), whereas `common_symbol` correctly yields ARBETH.",
          "5. Exactly one match: use its `code`.",
          "6. More than one match: disambiguate on `contract_address`. A bare asset name means the native asset, which has a null `contract_address`; wrapped or bridged variants carry one. If the user supplied a token contract address, match it exactly. If still ambiguous, STOP and ask the user which asset they mean — never guess.",
          "7. No match: `common_symbol` may simply be absent for this asset. Fall back to matching `code` and `name`, then confirm the chosen entry with the user by showing its `name` and `contract_address` before ordering. Do not substitute a near-match silently."
        ],
        "commonSymbolIsNotUnique": "`common_symbol` combined with `network` identifies one asset almost always, but not universally, and the exceptions are not safe to ignore. Two collisions exist: on network ETH the symbol ETH matches both the native asset ETH and Wrapped Ethereum WETH, separated by `contract_address` being null for the native one; and on network SOL the symbol USDC matches both USDCSOL and XO, an unrelated token whose `common_symbol` is mislabelled. Treating a multi-match as 'pick the first' can therefore select an entirely different asset than the user asked for. Always apply step 6.",
        "commonSymbolMayBeMissingOrOdd": "If no entry on the target network has a matching `common_symbol`, do not conclude the route is unavailable. Fall back to matching `code` and `name`, then confirm the specific asset with the user by showing its `name` and `contract_address` before creating an order. Never silently substitute a near-match.",
        "sendingTheResolvedAsset": "api-v2-orders accepts either the internal `code` or the `common_symbol`, each paired with the `network` value. Send the `code`: it is unambiguous by construction, whereas a symbol re-runs the ambiguity above server-side.",
        "strictness": "Send the `network` value exactly as api-v2-currencies gives it, and nothing else. External aliases such as ARBITRUM are now accepted on both routes, but only where the alias resolves unambiguously — it is corroborated against internal mappings and rejected when it does not resolve to exactly one network. The internal `network` value is never ambiguous, works on every path, and avoids the question entirely.",
        "networksEndpointNote": "api-v2-networks returns `network`, `native_currency`, `chain_id` and `is_evm`, with no human-readable chain names, so it cannot map a chain name to a code — use api-v2-currencies for that. It is useful in the other direction: if the user identifies a chain by its EIP-155 chain ID, `chain_id` resolves it to a `network` value. A null `chain_id` does not mean the network is non-EVM; read `is_evm` for that.",
        "commonSymbolSemantics": "`common_symbol` is not a curated user-facing ticker. It is the market symbol this asset maps to on an external trading venue, surfaced through the currency endpoint. Two consequences. It is null for roughly a quarter of the catalogue — about half fiat, but also around two dozen crypto assets including some widely traded ones — so a null does not mean the asset is unsupported. And for a few assets it names the market the asset is priced against rather than the asset's own ticker, which is why an unrelated token can appear to share a well-known symbol. It is still the best field for matching user intent, but treat a match as a candidate to be confirmed, not as proof of identity.",
        "preflightCheck": "Before you POST, look at the `code` and `network` you are about to put in `deposit_currency` and `withdraw_currency`. Every one of those four values must be a value you actually read from api-v2-currencies — not a word the user typed. If the network you are about to send does not appear as a `network` value in that response, you have skipped the resolution procedure: go back and run it. The user saying 'Arbitrum' does not make 'Arbitrum' or 'ARBITRUM' a network value; the value is ARB. This one check catches the most common cause of a rejected order."
      },
      "orderCreation": {
        "createOrderOnlyFromFreshRate": true,
        "freshRateMaxAgeSeconds": 20,
        "quoteStageMustNotRequireAddressUnlessApiRequiresIt": true,
        "fixedRateRequiresPayoutAndRefundBeforeQuote": true,
        "doNotUseDryRunUnlessDocumented": true,
        "doNotCreateOrderIfUserIsNotReadyToPayImmediately": true
      },
      "responseShape": {
        "routeVariance": "Route selection is decided server-side from the request and is not requested by the agent. The custodial and non-custodial DeFi routes return different fields and different limits for the same query. Do not treat a missing optional field as an error.",
        "withdrawAmountMayBeAbsent": "api-v2-rates omits `withdraw_amount` on the DeFi route. Do not abort. Quote the indicative amount only if present, otherwise proceed and state the received amount from the order-creation response, which carries the field — but only if it is non-zero. A zero there means the amount did not resolve, not that the user receives nothing: say the amount is not yet available rather than quoting zero.",
        "limitsAreRouteSpecific": "min_deposit_amount and max_deposit_amount differ between routes. Always read them from the same response you are quoting from, never from a previous route's response.",
        "paymentWindow": "Two fields, one rule that works on every order. If `payment_window_minutes` is 0 there is no payment window at all: `fixed_rate_deadline` will equal the creation time, which is not an expiry. Do not show it, do not compute a countdown from it, and never tell the user the order has already expired. Say there is no deadline. Otherwise `fixed_rate_deadline` is the authoritative expiry — count down to that timestamp, and never derive a deadline yourself by adding `payment_window_minutes` to `created_on`. That arithmetic holds only on the custodial route, where the deadline is computed from the window. On the non-custodial DeFi route it does not: a DeFi order has no configured window, `payment_window_minutes` is reported as a constant 1 regardless, and the real expiry comes from the quote — so a floating DeFi order shows a window of 1 against a deadline roughly fifteen minutes away, and the arithmetic would tell the user their payment expires in one minute. On a fixed-rate order the deadline is short, around a minute, and is the moment after which the quote is dead: show it, and create the order only when the user has confirmed they are ready to send immediately. Route selection is server-side, so apply this same rule to every order rather than trying to work out which route you are on."
      },
      "orderCreationSemantics": {
        "successStatuses": "Both 201 and 200 are success. 201 means a new order was created. 200 means an identical request matched an order that already existed and had not yet been paid; it is returned with a refreshed deadline. Never treat 200 as a failure and never re-send the request to obtain one.",
        "idempotency": "A 200 is possible ONLY on the non-custodial DeFi route, ONLY while the matched order is still in its initial unpaid state, and ONLY for a request matching on currencies, networks, payout address, refund address, rate type and referral token. Note what is NOT in that list: the amount. Re-sending with a corrected amount does not mint a fresh order — it returns the earlier one, at the earlier amount, as a 200 you may misread as success. Once the user has sent the deposit the order leaves that state, and a repeat request mints a NEW order with a NEW deposit address. This describes why a 200 can appear. It is never a licence to re-send the request. The custodial route has no matching behaviour at all and mints a new order every time.",
        "neverRetryOrderCreation": "Never re-send a request to api-v2-orders to refresh, re-display or recover a deposit address, on either route. A second request can always produce a second order with a different address, leaving the user with two live addresses for one intended exchange. If you no longer hold the response, ask the user for the order reference and read it back with a GET rather than re-creating it. The question to ask before sending anything again is not what the status code was, but whether you know what happened. A response whose body names something wrong with the request itself — a currency or network that could not be resolved, an amount outside the stated limits, a malformed payout address — was rejected during validation, before any order existed: correct that specific thing and send once more. If instead you cannot see a response body, or it says only something generic such as 'Invalid request', or the request timed out or the connection failed, or the status is 5xx, then you do not know whether an order was created, and one may already be holding a deposit address. Do not send again in that case. Tell the user the attempt could not be confirmed, show them the payout address you used, and point them at support rather than starting over. The other permitted exception is a genuinely new order after a fixed-rate window has expired, which requires telling the user the previous instruction is dead and obtaining fresh confirmation that they are ready to pay; that is a new exchange, not a retry. The two routes fail differently: on the custodial route a duplicate request returns a different deposit address, splitting the user across two of them; on the DeFi route the address may be reused under a new order reference, so the funds arrive but you may be monitoring a reference they are not attached to and report it as unpaid.",
        "authoritativeFields": "Take the deposit address, deposit amount, order reference and expiry from the order-creation response, not from an earlier rate response. The received amount in that response is the creation-time estimate; when reporting completion, use the final settled amount observed while monitoring the order, not this figure."
      },
      "referralAttribution": {
        "header": "x-referral-token",
        "queryParameterAlternative": "The referral code may instead be supplied as a `ref` query parameter (for example `?ref=ai_floating`) on the same request. Verified equivalent to the header. Resolution order is header, then `ref`, then session. This is what makes the web path attribute correctly.",
        "required": true,
        "value": "One of the two codes in apiPolicy.referralCodes, chosen by rate type — see the selection rule there.",
        "note": "API-key requests are rejected without a referral token unless the key's profile allows non-referred orders. Sending the code in the request body is not supported on v2 and is silently ignored."
      },
      "endpointAuth": {
        "apiKeyRequired": [
          "api-v2-currencies",
          "api-v2-networks",
          "api-v2-pairs",
          "api-v2-rates",
          "api-v2-orders"
        ],
        "note": "Every v2 endpoint requires the Authorization header. api-v2-currencies and api-v2-networks sometimes answer an unauthenticated request with a 200 because their responses are cached and a cache hit is served before authentication runs; the same request can return 401 moments later. Do not design around that — always send the header. A 401 is expected behaviour, not an outage."
      }
    },
    "addressCollectionPolicy": {
      "quoteStage": "Do not require payout or refund address merely to show available routes, limits, or indicative rates unless the documented API endpoint explicitly requires it.",
      "beforeOrderCreation": "Before creating any order, collect and confirm the payout address and refund address for the relevant networks.",
      "fixedRate": "For fixed-rate orders, collect payout and refund addresses before the final fresh rate/order creation step because the payment window is very short.",
      "floatingRate": "For floating-rate orders, the agent may show an indicative quote before asking for addresses. Ask for payout/refund addresses only when the user wants to create the order.",
      "sameAddressAllowed": "If the source and destination networks are compatible and the API/product rules allow it, the agent may offer to use the same EVM address for payout and refund."
    },
    "conversationPolicy": {
      "defaultStyle": "simple_exchange_cashier",
      "principle": "Show the user only the next action needed to complete the exchange. Do not expose internal API fields, raw route codes, raw statuses, deadlines, endpoint names, or diagnostics unless they are safety-critical or the user asks for technical details.",
      "language": "Use the user's language. Keep default exchange messages short, direct, and action-oriented.",
      "defaultUserFlow": [
        "User states the desired exchange.",
        "Agent checks route availability and gives a short confirmation.",
        "Agent asks for the payout address and says the same compatible address can be used for refund when appropriate.",
        "Agent creates the order only after address confirmation.",
        "Agent shows the exact deposit amount, deposit token, deposit network, and deposit address.",
        "Agent monitors the order and tells the user when the status actually moves, not when the user says they paid. Never claim the payment has been seen before the order status shows it — on the non-custodial route there is no state meaning 'payment seen but unconfirmed'.",
        "When complete, agent confirms funds were sent, shows the final received amount, and shows the withdrawal transaction hash."
      ],
      "messageTemplates": {
        "routeFound": "I found a route. Send the address where you want to receive {receiveCurrency}. The same compatible address can be used for refund.",
        "paymentInstruction": "Exchange created. Send {depositAmount} {depositCurrency} on {depositNetwork} to: {depositAddress}",
        "paymentSafety": "Use only {depositCurrency} on {depositNetwork}. Do not send another token or network.",
        "monitoring": "Monitoring the exchange. I will tell you as soon as it moves.",
        "paymentDetected": "Your payment has been picked up. Processing the exchange.",
        "completed": "Done. Funds were sent to your address. Received: {receivedAmount} {receivedCurrency}. Tx: {withdrawTx}",
        "fixedRateReadyCheck": "This fixed-rate order has a very short payment window. Confirm you are ready to send immediately, then I will create a fresh order.",
        "expiredFixedRate": "This fixed-rate payment window is no longer safe to pay. I will create a fresh order instead."
      },
      "hideByDefault": [
        "raw route codes",
        "internal status names",
        "deadline unless payment window is short or safety-critical",
        "API endpoint names",
        "empty API fields",
        "debug explanations",
        "full request payloads",
        "full response bodies"
      ],
      "showAlwaysForSafety": [
        "exact deposit amount",
        "deposit token",
        "deposit network",
        "deposit address",
        "warning not to send another token or network",
        "fixed-rate expiry warning",
        "final received amount",
        "withdrawal transaction hash",
        "order reference, so the user can contact support"
      ],
      "technicalDetailsPolicy": "If the user asks for technical details, show concise details after the user-facing next step. Keep diagnostics separate from payment instructions."
    },
    "fixedRateUxPolicy": {
      "doNotAskUserToChooseFixedOrFloatingByInternalTermsFirst": true,
      "defaultToSimpleBestAvailableRoute": true,
      "explainFixedVsFloatingOnlyIfUserAsksOrIfBothOptionsNeedUserChoice": true,
      "askReadyToPayBeforeCreatingFixedRateOrder": true,
      "fixedRateWarning": "For fixed-rate orders, warn only when creating the order or when showing a fixed-rate option: the payment window is very short, so the user must be ready to send immediately.",
      "doNotExposeDepositAddressAfterDeadline": true
    },
    "exchangeModels": [
      {
        "name": "custodial",
        "description": "The user creates an order and sends funds to a deposit address controlled by N.exchange infrastructure. N.exchange processes the exchange and sends payout to the user-provided destination address. Custodial flows are subject to N.exchange Terms, eligibility, prohibited-jurisdiction, sanctions, AML/KYC, geoblocking, and route controls."
      },
      {
        "name": "non-custodial-defi",
        "description": "For supported DeFi routes, the deposit or execution path may be generated at the smart-contract level. The contract/order rules define whether funds can be processed to the requested payout address or returned/refunded. Agents should present contract, calldata, route, refund-path, and risk information when available, and must still respect route availability, sanctions, geoblocking, prohibited-use, and product-specific eligibility rules."
      }
    ],
    "rateModels": [
      {
        "name": "fixed-rate",
        "description": "The rate is locked for a very short payment window, commonly about one minute in the current flow. The agent must collect and confirm the payout address and refund address before creating a fixed-rate order, then create the order only when the user is ready to send the deposit immediately. The agent must show the locked rate, exact deposit amount, payout amount when available, payment deadline, payout address, refund address if required, and order reference."
      },
      {
        "name": "floating-rate",
        "description": "The final payout may depend on execution price, liquidity, network fees, and slippage. The agent must explain that the final received amount can differ from the indicative quote and should show minimum received amount or slippage parameters when available."
      }
    ],
    "recommendedFlow": [
      "Determine your own HTTP capability first — see clientCapabilities. If you cannot set request headers or cannot POST, use the web entrypoint rather than the API. Choosing a path you cannot execute is the most common way this flow fails.",
      "Read and apply the current N.exchange Terms at https://n.exchange/legal/terms.",
      "Check user eligibility, jurisdiction, sanctions restrictions, route availability, and product-specific requirements before offering or creating an order.",
      "Do not attempt to determine the user's jurisdiction. Route selection is decided server-side from the request; if a custodial route is unavailable the API returns a DeFi route instead. Never ask a user to self-declare a location or personhood in order to obtain a different route.",
      "Identify whether the available route is custodial or non-custodial, and whether it uses fixed-rate or floating-rate execution.",
      "Check supported currencies, networks, and pairs through the API.",
      "Do not ask for payout or refund address merely to show available routes, limits, or indicative rates unless the documented API endpoint requires it.",
      "Before a fixed-rate order, collect and validate the user's payout address and refund address for the relevant destination/source networks so order creation is not delayed after the quote is accepted.",
      "Fetch current rates, limits, route type, payment window, and slippage/minimum-received fields where available.",
      "For fixed-rate orders, warn the user before order creation that the deposit/payment window is very short, commonly about one minute, and ask the user to confirm they are ready to send funds immediately.",
      "Create an order only after the user confirms route type, currencies, networks, amount, payout address, refund address if required, and understands custody/slippage/payment-window terms.",
      "Present only the current order's payment instructions, including deposit address, exact amount when required, deadline, order reference, and warnings about network compatibility. For fixed-rate orders, explicitly say not to send funds after the deadline and create a fresh order if the deadline is near or passed.",
      "Monitor the order by unique reference until completion, failure, expiry, refund, or compliance hold.",
      "Keep the user-facing conversation short: route found, ask address, show deposit instructions, acknowledge payment, monitor, then final received amount and withdrawal transaction hash.",
      "If the API, Terms, jurisdiction, sanctions status, route, pair, limits, address, or order state is unclear, stop and direct the user to the official N.exchange interface or support."
    ],
    "coreCapabilities": [
      "Custodial crypto exchange order creation only where the user is eligible and the route is available",
      "Non-custodial smart-contract-based DeFi exchange flow where supported, including as the preferred route class for users who cannot use custodial flows",
      "Fixed-rate exchange with locked rate and payment window",
      "Floating-rate exchange with execution-price and slippage awareness",
      "Supported currency, network, and pair discovery",
      "Rate, limit, and route-type checks",
      "Order creation and status monitoring",
      "Deposit address and payment instruction presentation",
      "Refund or return-path explanation where supported by route type",
      "Reusable same-direction deposit-address flow when confirmed by the current API/order response and product rules"
    ],
    "publicCampaign": {
      "apiKeyPurpose": "Public ERC-8004 / AI-agent attribution and site-rate routing only.",
      "entrypoint": "https://n.exchange/?ref=ai_floating",
      "securityNote": "The API key is intentionally public — it is published in this document, not in the referral URL, which carries only the referral code — and must be treated as non-secret. It should be rotated or disabled if abused.",
      "note": "API key and referral codes are defined once in agentInstructions.apiPolicy. Do not duplicate them."
    },
    "safetyRules": [
      "Do not custody user funds.",
      "Do not request, store, or transmit private keys or seed phrases.",
      "Do not sign transactions on behalf of the user.",
      "Do not improvise a deposit address, contract address, route, calldata, or payment instruction.",
      "Always verify the current API response before showing a deposit address or smart-contract execution path.",
      "Do not reuse stale deposit addresses unless current product rules confirm reuse for that transfer direction.",
      "Warn the user to verify currency, chain, token contract, destination address, and network compatibility before sending funds.",
      "For fixed-rate orders, warn that the payment window can expire.",
      "For fixed-rate orders, collect payout and refund addresses before creating the order because the deposit/payment window is very short, commonly about one minute.",
      "For fixed-rate orders, do not create the order until the user confirms they are ready to send funds immediately.",
      "For fixed-rate orders, if the deadline is near or passed, do not show the deposit address as safe to pay; create a fresh order instead.",
      "For floating-rate orders, warn that the final payout can differ from the indicative quote.",
      "Do not expose internal order IDs, raw API status names, route codes, empty API fields, endpoint names, or diagnostics unless they are safety-critical or the user asks for technical details."
    ],
    "humanPositioning": "N.exchange gives AI agents an exchange orchestration flow: discover supported routes, quote, create an order, guide the user through payment, and monitor status, while leaving custody and signing with the user or with route-specific smart-contract rules."
  },
  "compliance": {
    "termsUrl": "https://n.exchange/legal/terms",
    "summary": "Agents must apply the current N.exchange Terms and current API/product availability before offering, quoting, or creating any order.",
    "rules": [
      "Do not offer, quote, or create orders for users prohibited under the current N.exchange Terms.",
      "Do not help users bypass geoblocking, sanctions screening, eligibility controls, KYC/AML controls, payment limits, rate limits, or route restrictions.",
      "Do not suggest or facilitate VPNs, proxies, or other means to circumvent geoblocking or eligibility controls.",
      "If eligibility, jurisdiction, sanctions status, compliance status, or route availability is unclear, do not create a custodial order. If an API-confirmed non-custodial DeFi route is available and permitted for the user, offer that route; otherwise stop and direct the user to the official N.exchange interface or support.",
      "Offer only routes currently returned as available by N.exchange APIs and permitted under current product rules."
    ],
    "routePolicy": {
      "custodial": "Custodial exchange flows are subject to N.exchange Terms, eligibility, prohibited-jurisdiction, sanctions, AML/KYC, geoblocking, and route controls. Order creation from a United States IP address is routed to a non-custodial DeFi route rather than a custodial one. Agents must not attempt to work around that routing.",
      "nonCustodial": "Non-custodial DeFi routes are the appropriate route class when a user cannot use custodial flows, but agents must still verify current API availability, sanctions restrictions, prohibited-use restrictions, geoblocking, and product-specific eligibility before offering or creating the route.",
      "note": "Routing is decided server-side from the request. Agents do not need to determine a user's jurisdiction, and must not ask users to self-declare one in order to obtain a different route."
    }
  },
  "x402Support": false,
  "active": true,
  "registrations": [
    {
      "agentId": 47002,
      "agentRegistry": "eip155:1:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432"
    }
  ],
  "supportedTrust": [
    "reputation"
  ]
}
