Aller au contenu
KOTOVADOCS
Lancer l'App

Quickstart

Afficher en Markdown

Ce contenu n’est pas encore disponible dans votre langue.

This page takes you from a Kotova account to a first order, one step at a time. It assumes your integration runs on a server: the API key is a secret, and it belongs there rather than in a browser or a mobile app.

The examples swap 0.05 BTC on the Bitcoin network for USDT on TRON. Every path is relative to the base URL https://api.kotova.io/x/v1.

  1. Prepare your account. Sign in at app.kotova.io with an account whose e-mail address is confirmed. A disposable address cannot be used for API access. Then:

    • turn on two-factor authentication with an authenticator app, under Personal data in your account;
    • open the account API page and choose Generate referral code. This creates your affiliate profile and accepts the affiliate terms. Your API key belongs to this profile, and the orders you create with it are attributed to it.
  2. Create your API key. On the account API page, accept the API Terms of Use, choose Create API key and enter the 6-digit code from your authenticator app. Backup codes cannot be used here.

    The page then shows your secret key, which starts with ktv_sk_. It is shown once and never again, so copy it straight into your server’s secret store. The examples on these pages read it from an environment variable named KOTOVA_API_KEY. See Authentication.

  3. Check that the API answers. GET /health needs no key. The JavaScript and Python snippets also set up what the later steps use: the base URL, the Authorization header, and placeholders for your user’s IP address, your user’s receiving and refund addresses, and your own status display.

    Terminal window
    curl -sS https://api.kotova.io/x/v1/health

    An excerpt of the response:

    {
    "status": "ok",
    "api_version": "v1",
    "time": "2026-11-10T10:15:04Z",
    "catalog_version": "394da0f044c4"
    }

    To make this call from your browser, use the console in Check availability.

  4. Find the currency and network codes. GET /currencies lists every currency with the networks it can be sent on (send) and received on (receive). A quote names each side by currency and network. Both endpoints on this step need no key.

    Terminal window
    curl -sS https://api.kotova.io/x/v1/currencies

    To see what one currency can be swapped into, ask GET /pairs with from and from_network:

    Terminal window
    curl -sS "https://api.kotova.io/x/v1/pairs?from=BTC&from_network=btc"

    See Currencies and icons.

  5. Request a quote. POST /quote asks every eligible source and returns the best offer. rate_type is required (variable or fixed). Send your user’s public IP address as end_user_ip: some sources only quote when they have it, and the quote says which ones were skipped without it. Use lang for the language of the source notice.

    Terminal window
    curl -sS https://api.kotova.io/x/v1/quote \
    -H "Authorization: Bearer $KOTOVA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
    "from": {"currency": "BTC", "network": "btc"},
    "to": {"currency": "USDT", "network": "trx"},
    "amount": "0.05",
    "amount_type": "from",
    "rate_type": "variable",
    "end_user_ip": "93.184.216.34",
    "lang": "en"
    }'

    An excerpt of the response:

    {
    "quote_id": "q_5mJc2Vq9XkT3nR8bYw1LdP",
    "expires_at": "2026-11-10T10:17:03Z",
    "rate_type": "variable",
    "from": { "currency": "BTC", "network": "btc", "amount": "0.05" },
    "to": { "currency": "USDT", "network": "trx", "amount": "3389.8" },
    "requirements": {
    "refund_address": "optional",
    "to_memo": "not_supported",
    "refund_memo": "not_supported"
    },
    "provider": {
    "name": "Kotova X",
    "icon": {
    "url": "https://cdn.kotova.io/images/brand/kotova-x/icon.svg",
    "fallback_url": "https://assets.kotova.io/images/brand/kotova-x/icon.svg"
    }
    },
    "source": {
    "slug": "sideshift",
    "name": "SideShift",
    "notice": {
    "text": "The exchange service is provided by SideShift. Creating an order confirms your agreement with the SideShift rules.",
    "link_text": "SideShift rules",
    "link_url": "https://sideshift.ai/legal",
    "lang": "en"
    }
    },
    "fallback_sources": [
    {
    "source": {
    "slug": "changenow",
    "name": "ChangeNOW",
    "notice": {
    "text": "The exchange service is provided by ChangeNOW. Creating an order confirms your agreement with the ChangeNOW rules.",
    "link_text": "ChangeNOW rules",
    "link_url": "https://changenow.io/terms-of-use",
    "lang": "en"
    }
    },
    "from": { "amount": "0.05" },
    "to": { "amount": "3376.2" },
    "requirements": { "refund_address": "optional" }
    }
    ],
    "warnings": []
    }

    The quote_id can be used for one order, until expires_at: 120 seconds after the source answered for a variable quote, 60 seconds for a fixed one. See Quotes.

  6. Show the quote with the required notices. Show your user the amounts, with Kotova X named as the provider, by name and icon (provider.name, provider.icon). Before your user confirms, show the source notice: source.notice.text, with the words in link_text linked to link_url. Show the notice of each of the quote’s fallback_sources as well, by the same rules: when the quote’s source cannot take the order, it is placed with the first of them that can. The fallback notices may follow the quote’s notice, including in an expandable section placed directly next to it. All of this is mandatory. See Display requirements.

  7. Create the order. When your user confirms, send POST /orders with the quote_id, the address your user receives on (to_address) and, if you like, your own reference (partner_order_id).

    We recommend sending refund_address too: your user’s address on the network they send from, with refund_memo when that address needs a memo. Where the source takes it with the order, it goes to the source then, so a refund needs no extra step, and the quote’s fallback sources that need one stay eligible. It is required only when the quote says requirements.refund_address: "required". Ask for it in the same form as the address your user receives on (see Asking for the addresses).

    Send an Idempotency-Key header and store it with your own order. If the request times out, send it again with the same key and the same body: you get the order that was created, never a second one. Creating an order costs 50 units of your rate limit.

    If you do not show the notices of the fallback sources, add "retry_next_best_source": false to the body: the order is then placed only with the quote’s source. See Next best source.

    Terminal window
    curl -sS https://api.kotova.io/x/v1/orders \
    -H "Authorization: Bearer $KOTOVA_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: 3f1c9a52-7d0e-4b8a-9c61-2e5f4a7b8d90" \
    -d '{
    "quote_id": "q_5mJc2Vq9XkT3nR8bYw1LdP",
    "to_address": "REPLACE_WITH_YOUR_USERS_TRON_ADDRESS",
    "refund_address": "REPLACE_WITH_YOUR_USERS_BTC_ADDRESS",
    "partner_order_id": "shop-order-1042"
    }'
  8. Show the deposit instructions. The API answers 201 Created with the order. An excerpt, with the addresses shortened:

    {
    "id": "X-7KQ2ZD",
    "status": "waiting_for_deposit",
    "is_final": false,
    "expires_at": "2026-11-10T11:15:39Z",
    "deposit": {
    "address": "bc1q9h7g…zq0p2ne",
    "memo": null,
    "memo_label": null,
    "amount": "0.05"
    },
    "order_url": "https://app.kotova.io/x/X-7KQ2ZD"
    }

    Show your user deposit.amount of from.currency on from.network, the deposit.address it goes to and, when it is set, deposit.memo under the label in deposit.memo_label. A deposit without its memo may not be credited. The deposit address belongs to the order’s source, and the deposit is due before expires_at. When the order was placed with a fallback source, its source names it, its amounts are that source’s, and warnings has source_fallback: show the order’s source and amounts, not the quote’s.

    You may give your user the order_url if you are happy for them to follow and resolve the order on Kotova: it opens the order page on app.kotova.io, which they unlock with the address they receive on. To keep them in your app, show the order yourself from GET /orders/{id}, and, until the API has endpoints for an order’s choices, send them to status_detail.resolve_url only when an order needs a decision.

  9. Follow the order until it is final. Read the order with GET /orders/{id} every 15 to 30 seconds and show your user its status, until is_final is true. Each read costs 1 unit; the API refreshes the order from its source at most once every 10 seconds while it is in progress, and once a minute while it is only being followed up (see Reading an order).

    Terminal window
    curl -sS https://api.kotova.io/x/v1/orders/X-7KQ2ZD \
    -H "Authorization: Bearer $KOTOVA_API_KEY"

    An order in action_required needs attention: status_detail says why and whether your user can act on the order page. When the reason is payout_on_hold, write to api@kotova.io with the order id. Every status, and what to show for it, is in Order statuses.

A sandbox is not available yet. Requesting a quote has no side effects, so you can build and test everything up to the order without creating anything. An order you create is a real order at its source:

  • If nobody sends the deposit, the order expires and nothing is owed (creating it still used 50 units of your rate limit). Until it expires it counts towards your account’s limit of open orders waiting for a deposit (see Order caps).
  • To test the whole flow, create an order for a small amount, send the deposit from a wallet you control and receive the payout at an address you control.
  • The Try it consoles on these pages call the production API with your key. The order console asks you to confirm every time before it creates an order.