# Display requirements

> What every integration must show: Kotova X by name and icon as the provider, and the source notices before your user confirms an order.

- Source: https://docs.kotova.io/x/api/display-requirements
- API base URL: https://api.kotova.io/x/v1
- OpenAPI document: https://api.kotova.io/x/v1/openapi.json

Two things are mandatory wherever your application presents a Kotova X quote or
order. Kotova X must appear by name and icon as the provider, and the notice of every
source that may execute the order must appear before your user confirms. Both are
conditions of using the API; see also the [API Terms of Use](https://kotova.io/terms/api).

## What you must show

| | What | Where | From |
|---|---|---|---|
| 1 | The name **Kotova X** and the Kotova X icon | Wherever you present a Kotova X quote or order | The `provider` block |
| 2 | The notice of the quote's source and, unless the order is sent with `retry_next_best_source: false`, the notices of its fallback sources, each with its link | Before your user confirms the order, and before it is created | `source.notice` and `fallback_sources[].source.notice` in the quote |

`GET /sources` restates both in its `attribution` block:
`provider_display_required` and `source_notice_required_before_order` are `true`, and
`docs_url` points to this page. See [Sources](https://docs.kotova.io/x/api/sources#the-attribution-flags).

## Show Kotova X as the provider

Kotova X is the provider of the service: it compares the sources' offers and routes the
order to the one that made the best offer. Show it by name and icon wherever your
application presents a Kotova X quote or order: the offer itself, the confirmation step,
the order's status view, and any receipt or order history that lists it.

- **The name** is exactly `Kotova X`, with a space and a capital X. Never `KotovaX`,
  `Kotova-X` or a translation.
- **The icon** is the Kotova X icon from the files below, shown next to the name.
- **The data** is the `provider` block, which comes with every quote, every order and
  `GET /sources`, and is the same everywhere:

```json
{
  "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"
  },
  "icon_png": {
    "url": "https://cdn.kotova.io/images/brand/kotova-x/icon-256.png",
    "fallback_url": "https://assets.kotova.io/images/brand/kotova-x/icon-256.png"
  },
  "website_url": "https://app.kotova.io"
}
```

You may link the name or the icon to `website_url`, the Kotova X app.

### The Kotova X icon

| File | Size | URL | Fallback URL |
|---|---|---|---|
| SVG (`provider.icon`) | Scalable | `https://cdn.kotova.io/images/brand/kotova-x/icon.svg` | `https://assets.kotova.io/images/brand/kotova-x/icon.svg` |
| PNG | 64 × 64 px | `https://cdn.kotova.io/images/brand/kotova-x/icon-64.png` | `https://assets.kotova.io/images/brand/kotova-x/icon-64.png` |
| PNG | 128 × 128 px | `https://cdn.kotova.io/images/brand/kotova-x/icon-128.png` | `https://assets.kotova.io/images/brand/kotova-x/icon-128.png` |
| PNG (`provider.icon_png`) | 256 × 256 px | `https://cdn.kotova.io/images/brand/kotova-x/icon-256.png` | `https://assets.kotova.io/images/brand/kotova-x/icon-256.png` |

The fallback URL is the same file on Kotova's mirror. If the first URL fails to load,
retry once with the fallback, as described in
[Icons](https://docs.kotova.io/x/api/currencies#icons). You may link to these files or self-host unmodified
copies of them.

- Show the icon at 24 pixels or larger.
- Use it unmodified: no recolouring, distortion, rotation or shadow.
- Keep a clear space around it, and do not place it on a busy background. The icon is a
  dark tile, so it reads on light and dark backgrounds alike.

## Show the source notice before your user confirms

Every quote names the source that will execute the order, and carries that source's
notice in `source.notice`:

```json
{
  "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"
}
```

Show it before your user confirms the order:

- **Word for word.** Show `notice.text` as it is. Do not shorten it, reword it, translate
  it yourself or replace the source's name.
- **With its link.** `notice.link_text` is part of `notice.text`. Render that part as a
  link to `notice.link_url`.
- **At the right moment.** Before your user confirms, and before the order is created.
  We recommend showing it in the same view as the control that creates the order,
  visible without an extra click.
- **Never pre-accepted.** Your user's confirmation is their agreement. Do not accept the
  notice on their behalf, for example with a consent box that is already ticked.
- **For the right source.** Take the notices from the quote your user is confirming.
  The order is created at that quote's source or one of its fallback sources, and a new
  quote can name different ones.

The notice is the line the Kotova X app shows before an order is created. It names the
source because the source executes the swap and its rules apply to the order. A source
without rules of its own, such as a decentralised protocol, links to Kotova's Terms of
Service instead; its `terms_url` is then `null`.

### Fallback sources

By default, when the quote's source cannot take the order, `POST /orders` places it
with the first of the quote's `fallback_sources` that can (see
[Next best source](https://docs.kotova.io/x/api/orders#next-best-source)). Your user then agrees to that
source's rules, so its notice must have been shown too.

- **Show every fallback notice by the same rules as the quote's notice**: word for
  word, with its link, before your user confirms and before the order is created, and
  never pre-accepted.
- **The one difference is where.** The fallback notices may be shown after the quote's
  notice, including in an expandable section placed directly next to it. For example,
  directly below the quote's notice, a line "If SideShift can't take the order, it is
  placed with:" followed by each fallback notice in order, either listed in full or in
  an expandable section with that line as its summary. The line that introduces them is
  your own wording.
- **When `fallback_sources` is empty**, the quote's notice is all there is to show.
- **If you cannot show them**, send `"retry_next_best_source": false` with the order.
  Only the quote's source is then tried, and the order fails when it cannot take it.

### After the order is created

The order's `source` is the source that executes it. After a fallback, it is not the
quote's source: the 201 carries a `source_fallback` warning, and the order's amounts
are that source's. From then on, show the order's source, and its notice where you
show one, in the order view, status updates, receipts and order history, never the
quote's.

### Your user's language

Ask for the notice in your user's language with `lang`. `POST /quote`, `POST /orders`,
`GET /orders/{id}` and `GET /sources` all take it. The supported values are `en` (the
default), `de`, `it`, `es`, `fr` and `ru`; a region suffix such as `de-AT` is accepted.
Any other value gives the English notice and an `unsupported_lang` warning. `notice.lang`
says which language you got.

### The notice in six languages

For reference, these are the six forms of the notice. `{source}` stands for the source's
`name`, and the part in bold is `link_text`. When the link goes to Kotova's Terms of
Service, `link_url` is `https://kotova.io/terms/service?lang=` followed by the language
code.

| `lang` | Source with its own rules | Source that links to Kotova's Terms of Service |
|---|---|---|
| `en` | The exchange service is provided by `{source}`. Creating an order confirms your agreement with the **`{source}` rules**. | The exchange service is provided by `{source}`. Creating an order confirms your agreement with the **Kotova Terms of Service**. |
| `de` | Der Tauschdienst wird von `{source}` bereitgestellt. Die Erstellung eines Auftrags bestätigt Ihre Zustimmung zu den **`{source}`-Regeln**. | Der Tauschdienst wird von `{source}` bereitgestellt. Die Erstellung eines Auftrags bestätigt Ihre Zustimmung zu den **Kotova-Nutzungsbedingungen**. |
| `it` | Il servizio di scambio è fornito da `{source}`. La creazione di un ordine conferma il tuo accordo con le **regole di `{source}`**. | Il servizio di scambio è fornito da `{source}`. La creazione di un ordine conferma il tuo accordo con le **Condizioni di servizio di Kotova**. |
| `es` | El servicio de intercambio es proporcionado por `{source}`. La creación de una orden confirma su aceptación de las **reglas de `{source}`**. | El servicio de intercambio es proporcionado por `{source}`. La creación de una orden confirma su aceptación de las **Condiciones de servicio de Kotova**. |
| `fr` | Le service d'échange est fourni par `{source}`. La création d'un ordre confirme votre accord avec les **règles de `{source}`**. | Le service d'échange est fourni par `{source}`. La création d'un ordre confirme votre accord avec les **Conditions d'utilisation de Kotova**. |
| `ru` | Сервис обмена предоставлен `{source}`. Создание заказа подтверждает ваше согласие с **правилами `{source}`**. | Сервис обмена предоставлен `{source}`. Создание заказа подтверждает ваше согласие с **Условиями использования Kotova**. |

> [!WARNING]
> **Always show the notice the API returns**
>
> Use this table to plan your layout, not to build the notice. A source's name, its rules
> link and the wording itself can change, and the API always returns the current line.

## Source names and logos

Showing the source's name and logo anywhere else is optional. A quote's and an order's
`source` block carries `name` and `icon`; `GET /sources` carries them for every source.
When `icon` is `null`, the source's logo may not be shown: use the name alone.

Source logos are their owners' trademarks. Kotova grants no licence to them. If you show
one, use it only to identify the source, unmodified, without suggesting that the source
endorses your application, and at your own risk.

## Describing the service

Do:

- Say that Kotova X compares the offers of independent sources and routes the order to
  the best one.
- Say that your user's funds go directly to the source that executes the swap, and never
  pass through Kotova.
- Call the party that executes the swap the source, and name it.
- Show when a quote expires (`expires_at`), and request a new quote once it has passed.
- Once the order exists, show the amounts and the source from the order. A quote fixes
  the sources and the pair; the order's amounts and source are the ones that apply.
- Say, where identity checks come up, that Kotova performs none itself and that
  centralised sources may perform them case by case.

Do not:

- Call Kotova or Kotova X an exchange or a custodian, or say that Kotova executes swaps
  or holds funds.
- Present a source as the provider, or Kotova X as the source.
- Show a quote as executable after its `expires_at`. Creating an order from it fails
  with a 410 [`quote_expired`](https://docs.kotova.io/x/api/errors#quote_expired).
- Hide, shorten, reword or translate a notice yourself, accept it on your user's behalf,
  or show it only after the order is created. The one exception: the fallback sources'
  notices may sit in an expandable section placed directly next to the quote's notice
  (see [Fallback sources](https://docs.kotova.io/x/api/display-requirements#fallback-sources)).
- Leave out the notices of the fallback sources when the order is sent without
  `retry_next_best_source: false`, or put them in an expandable section anywhere but
  directly next to the quote's notice.
- Alter the Kotova X name or icon, or show one without the other.
- Promise anything about rates, timing or the outcome of an order beyond what the quote
  and the order say.

## Asking for the addresses

This is a recommendation, not a requirement. Ask for the refund address in the same
form as the address your user receives on, before they confirm:

- **Both addresses together.** Show a field for the address your user receives on
  (`to_address`, on the `to` network) and one for their refund address
  (`refund_address`, on the `from` network) side by side, each labelled with its
  currency and network so that the two are not mixed up.
- **The refund address as recommended.** Make it optional unless the quote's
  `requirements.refund_address` is `required`, and say what it is for: if the swap
  cannot complete, the deposit goes back there. Sent with the order, it goes to the
  source where the source takes it then, and keeps more of the quote's fallback sources
  eligible (see [Refund addresses](https://docs.kotova.io/x/api/orders#refund-addresses)).
- **A memo field next to each address** whose network takes one (the quote's
  `requirements.to_memo` or `requirements.refund_memo` is `optional`), for an address
  at an exchange account or another address that needs a memo.
- **A check before confirming.** [`POST /addresses/validate`](https://docs.kotova.io/x/api/utilities)
  checks each address against its network's format.

## Example HTML

A minimal confirmation view: Kotova X as the provider, the offer, the address your user
receives on and their refund address, the source notice with its link, the notices of
the fallback sources in an expandable section directly below it, and the confirm
button.
The values come from the quote; the ones below are the documentation's
[example quote](https://docs.kotova.io/x/api/quotes#response).

```html
<form class="kx-offer">
  <p class="kx-provider">
    <img src="https://cdn.kotova.io/images/brand/kotova-x/icon.svg"
         onerror="this.onerror = null; this.src = 'https://assets.kotova.io/images/brand/kotova-x/icon.svg';"
         alt="" width="24" height="24">
    <span>Kotova X</span>
  </p>

  <p>You send 0.05 BTC and receive about 3389.8 USDT (TRON) through SideShift.</p>

  <label>
    Your USDT (TRON) address
    <input name="to_address" autocomplete="off" spellcheck="false" required>
  </label>
  <label>
    Your BTC refund address (recommended: if the swap cannot complete, your BTC goes back here)
    <input name="refund_address" autocomplete="off" spellcheck="false">
  </label>

  <p class="kx-notice" lang="en">
    The exchange service is provided by SideShift. Creating an order confirms your
    agreement with the
    <a href="https://sideshift.ai/legal" target="_blank" rel="noopener noreferrer">SideShift rules</a>.
  </p>

  <details class="kx-fallbacks">
    <summary>If SideShift can't take the order, it is placed with:</summary>
    <ol>
      <li lang="en">
        The exchange service is provided by ChangeNOW. Creating an order confirms your
        agreement with the
        <a href="https://changenow.io/terms-of-use" target="_blank" rel="noopener noreferrer">ChangeNOW rules</a>.
      </li>
      <li lang="en">
        The exchange service is provided by Changelly. Creating an order confirms your
        agreement with the
        <a href="https://changelly.com/terms-of-use" target="_blank" rel="noopener noreferrer">Changelly rules</a>.
      </li>
    </ol>
  </details>

  <button type="submit">Create order</button>
</form>
```

The same notices built from the API's answer. They are set as text, never HTML, so
nothing in the answer can inject HTML into your page, and the confirm button turns off
when the quote expires:

```js
// quote: the JSON answer of POST /quote.
function renderNotice(el, notice) {
  const link = document.createElement('a');
  link.href = notice.link_url;
  link.target = '_blank';
  link.rel = 'noopener noreferrer';
  link.textContent = notice.link_text;

  const at = notice.text.indexOf(notice.link_text);
  if (at === -1) {
    el.replaceChildren(notice.text, ' ', link);
  } else {
    el.replaceChildren(
      notice.text.slice(0, at),
      link,
      notice.text.slice(at + notice.link_text.length)
    );
  }
  el.lang = notice.lang;
}

renderNotice(document.querySelector('.kx-notice'), quote.source.notice);

const fallbacks = document.querySelector('.kx-fallbacks');
fallbacks.hidden = quote.fallback_sources.length === 0;
fallbacks.querySelector('summary').textContent =
  `If ${quote.source.name} can't take the order, it is placed with:`;
fallbacks.querySelector('ol').replaceChildren(
  ...quote.fallback_sources.map((fallback) => {
    const item = document.createElement('li');
    renderNotice(item, fallback.source.notice);
    return item;
  })
);

const button = document.querySelector('.kx-offer button');
const msLeft = Date.parse(quote.expires_at) - Date.now();
setTimeout(() => {
  button.disabled = true; // the quote has expired: request a new one
}, Math.max(0, msLeft));
```
