Developers

Integrating with Deneb

This page is for teams that build on Minter (wallets, Telegram bots and Mini Apps, games, websites) and want to connect to Deneb: the explorer at https://denebnav.app and the DEX at https://dex.denebnav.app. It lists every way to integrate, what each one needs on your side and its honest status.

Status labels:

  • Works now - live on dex.denebnav.app, you can use it today.

  • Open for registration - the Deneb side works; you register your product in the developer cabinet and it appears on the DEX after moderation.

  • In progress - the contract is written, the Deneb side is being built.

  • Planned - agreed direction, no contract yet.

Which way fits you

Who you areWayStatus
Website, game, bot or channel that wants to send users to a swap1. Swap linkWorks now
Telegram Mini App or bot that holds Minter keys (no WalletConnect)2. Link signingOpen for registration
Wallet that supports WalletConnect v23. WalletConnect, minter:1Planned
App that wants prices or swaps inside its own interface4. Prices and swap routes APIPlanned

A Telegram Mini App is a web page, so the same Mini App can also connect over WalletConnect (way 3) once that is available. Link signing is the way for it now.

You can combine ways: for example, a wallet bot can put swap links in its messages today and add link signing next.

Status: works now.

A plain link to the DEX with the pair and, optionally, the amount filled in. No SDK, no API key, no embedding.

https://dex.denebnav.app/swap?from=BIP&to=HUB&amount=100

The user lands on the swap screen, sees a fresh quote from Deneb's own node, connects a wallet on the DEX and decides. The link never trades by itself: it only fills in the form.

ParameterMeaningExample
fromCoin the user sells: coin id or ticker0, BIP, HUB
toCoin the user buys: coin id or ticker1902, USDTBSC
amountAmount of from to sell, decimal with a dot, at most 18 fraction digits100, 12.5
amtThe same amount in pip (1 coin = 10^18 pip), integer; wins over amount12500000000000000000
  • All parameters are optional. Without them the DEX opens its default pair, BIP to USDTBSC.

  • Tickers are case-insensitive. A value of digits only is a coin id (0 is BIP). Ids never change, a ticker names whichever coin holds it now, so prefer ids in long-lived links.

  • Only coins that have a pool can be traded.

  • Anything invalid (unknown coin, malformed amount, value longer than 64 characters) is ignored silently and that side falls back to the default pair. The user never sees an error page.

  • In the regular (non-PRO) view the swap card trades one coin against BIP, so the amount is kept only when BIP is one side of the pair.

  • Prices, routes and minimum amounts cannot be passed in the link.

  • Open the link in a new tab or the system browser. The DEX refuses to be shown in an <iframe>.

  • Use only https://dex.denebnav.app/swap as the entry point.

What you do: build the link with URLSearchParams (or your language's equivalent) and put it behind a button.

const url = new URL('https://dex.denebnav.app/swap');
url.search = new URLSearchParams({ from: 'BIP', to: 'HUB', amount: '100' }).toString();

Full reference with more examples and a button snippet: swap-link.md.

Status: open for registration. The Deneb signing service works: https://dex.denebnav.app/api/sign/v1 is live in production. Register your wallet in the developer cabinet (see How to get access); it appears under "Other wallets" on the DEX after a Deneb moderator publishes it. The picker is switched on for users after the first wallet passes moderation. The protocol is still a draft, not frozen: fields are only added, never change meaning, and the places that may change are marked [draft] in connect.md, §9.

For wallets that have no WalletConnect: Telegram Mini Apps, Telegram bots, mobile apps with deep links. The DEX keeps a short-lived request on its server and passes your wallet only an opaque id in a link. Your wallet fetches the request from a fixed Deneb address, shows it, signs with its own key and nonce, broadcasts and reports the hash back. The transaction itself is never in the link, and the key never leaves your wallet.

Flow.

  1. The user picks a swap on the DEX and chooses your wallet under "Other wallets".

  2. The DEX opens your link with the request id, for a Mini App https://t.me/<bot>?startapp=deneb_<id> (or ?start=deneb_<id> for a bot). Your Mini App receives the id in start_param.

  3. Your wallet calls POST /requests/{id}/claim and gets the request (envelope) and a one-time claimToken.

  4. Your wallet checks it, shows the swap, the user confirms, your wallet signs and broadcasts.

  5. Your wallet calls POST /requests/{id}/result with the hash and the signing address.

  6. The DEX finds the transaction in a block through its own node. Only that counts as success.

Base URL (hard-code it, never take it from a link or a request):

https://dex.denebnav.app/api/sign/v1

Endpoints for wallets.

Method and pathAuthPurpose
POST /requests/{id}/claim-Get the request. Works once.
POST /requests/{id}/resultBearer <claimToken> (session requests: <walletToken>)Report sent with hash, rejected with reason, or approved. Accepted once.
GET /sessions/{sid}/next?wait=25Bearer <walletToken>Long poll for the next session request.
POST /sessions/{sid}/revokeBearer <walletToken>Courtesy notice that the user revoked a session.
GET /wallets/disabled-Wallets the DEX has switched off.

What is carried. Only swaps: types 2, 3, 4, 23, 24, 25 per transaction. Send, Multisend, checks and every other type are never carried, and your wallet must refuse them even if the server returns them.

Two modes.

  • Per transaction (default): the user confirms every request in your wallet.

  • Session permission (optional, format final, not enabled on the DEX yet): the user grants once a set of limits (pool swaps 23, 24, 25 only, listed coins, caps per trade and in total, max slippage, transaction count, up to 24 h). Your wallet stores and enforces the limits next to the key; nothing on the DEX side can widen them.

What your wallet must check (short form of the checklist in §9.10):

  1. Take only the id from a link, matching ^deneb_(tx|cn|ss|sn)_[A-Za-z0-9_-]{22}$; ignore anything else.

  2. Show the service name from your own configuration; refuse if source in the envelope is not the host of the base URL.

  3. Check that chainId equals your wallet's network (production: "minter:1" only, otherwise refuse with wrong_source; never sign with another chain id), the id, the kind and expiresAt by your own clock.

  4. Never sign the same id twice.

  5. Parse the transaction strictly: allowed types only, no payload, no description, no unknown keys, amounts as pip strings, coin symbols from your own node. Show no text from the request except numbers and addresses.

  6. Set nonce, gas price and chain id yourself and broadcast yourself.

  7. Get your own quote from your own node, show "you receive at least X", warn on a big deviation and refuse a zero minimum.

  8. Ask the user every time; a request that came via a link is never signed without a prompt.

  9. Keep claimToken and walletToken in memory or secure storage, never in logs.

Full contract: connect.md, §9 Link signing (in English): envelope fields, limits, errors, delivery of session requests for bots and Mini Apps, and what the DEX checks.

3. WalletConnect, namespace minter:1

Status: planned. The contract is a draft and may change until it is frozen.

For wallets that support WalletConnect v2 (Sign API). The DEX proposes a session, the wallet approves it with one account, then the DEX sends minter_sendTransaction requests that the wallet shows, signs and broadcasts.

ItemValue
Namespaceminter
Mainnetminter:1
Testnetminter:2
Account (CAIP-10)minter:1:Mx + 40 lowercase hex characters
Methodminter_sendTransaction
EventsaccountsChanged, chainChanged

The chain reference is the chainId inside the signed Minter transaction; the wallet must check that they match. Request format, transaction types, events, checks after the answer and errors: connect.md, §1-8. These sections are currently in Russian.

4. Prices and swap routes API

Status: planned. No public endpoints yet, so there is nothing to call today.

For projects that want to show prices or build swaps inside their own interface instead of sending users to the DEX. If this is what you need, tell us which coins and pairs, whether you need prices only or full routes ready to sign, and how often you would ask. Until then, the swap link (way 1) is the way to hand a swap to Deneb.

How to get access

The swap link (way 1) needs no access: build the link and use it.

Register your wallet in the developer cabinet

Link signing (way 2) is set up by you, in the developer cabinet at https://developers.denebnav.app: Integrations → Add → Wallet. There is no list to send us and nothing to change on the Deneb side. Status: open for registration - the cabinet section works; you can register a wallet now.

  1. Sign in and turn on a passkey for your account (required for accounts that own a wallet).

  2. Create the wallet: name, icon (PNG or JPEG, we store and serve it), website, emergency contact.

  3. Add connect methods: Telegram Mini App https://t.me/<bot>/<app>?startapp=deneb_{id}, Telegram bot https://t.me/<bot>?startapp=deneb_{id} or ?start=deneb_{id}, a link on your own verified domain, and a marker if you also support WalletConnect minter:1. Only https://, a single {id}, no custom URL schemes. On desktop the DEX shows your link as a QR code.

  4. Prove ownership: a token from the cabinet in your bot's short description, or in https://<host>/.well-known/deneb-wallet.json on your domain.

  5. Press Send test request: a testnet request your wallet claims and answers. No real money, never on mainnet.

  6. Press Submit for review. A Deneb moderator publishes it once; DEX users then see it under Other wallets, marked as a third-party wallet. The "Other wallets" picker is not switched on for users yet: it is enabled after the first wallet passes moderation.

After publication you edit the name, icon and website freely. Changes to connect methods or the emergency contact go back to review, and the published version keeps working until they are approved. You can disable your wallet at any time, and so can Deneb; ownership is re-checked every 24 hours and a wallet whose bot or domain changed hands is disabled automatically.

Full rules: connect.md, §9.12 Registering your wallet.

Cabinet API behind the Wallets section

The Integrations section of the cabinet (the wallet form) uses these endpoints on the cabinet origin (https://developers.denebnav.app), with the cabinet session cookie. Writes are POST or PUT with a JSON body and the exact cabinet Origin. Errors are {"error": "<code>", "message": "…"}. Each answer with a wallet is {"wallet": {...}}: id, status (draft, review, rejected, published, disabled), disabled (who, when, reason, whether enabling was requested), and two versions, published (live) and pending (the draft, or the version in review or rejected), each with number, status, hash, name, icon_url, website, contact (email, verified), methods, review_comment.

EndpointWhat it does
GET /api/account/walletsYour wallets (at most 3 per account).
POST /api/account/wallets {"name","website","contact","methods"}Creates a wallet with a draft. Fields may be empty; filled fields are checked against the rules above.
GET /api/account/wallets/{id}One wallet.
PUT /api/account/wallets/{id} {"name","website","contact","methods"}Replaces the draft (the icon stays). After publication this is a new version; the published one keeps working. Not while in review.
POST /api/account/wallets/{id}/icon {"image":"<base64>"}Uploads the icon (PNG or JPEG, up to 512 KB) into the draft; it is re-encoded to a 256×256 PNG.
GET /api/account/wallets/icons/{sha256}.pngYour icon, served as an inert PNG.
POST /api/account/wallets/{id}/submitSends the draft to review. Needs a recent sign-in (10 minutes) until passkeys arrive.
POST /api/account/wallets/{id}/withdrawTakes the version in review back to a draft.
POST /api/account/wallets/{id}/disableDisables your published wallet at once.
POST /api/account/wallets/{id}/enableAsks to enable it again after you disabled it. Until passkeys and ownership checks arrive, a Deneb moderator does it.
POST /api/account/wallets/{id}/contactEmails a confirmation link to the emergency contact of the draft. The link works once, for 24 hours; a new one replaces it.
POST /api/account/wallets/contact/verify {"token"}Used by the page the link opens (no sign-in needed): confirms the contact.
POST /api/account/wallets/{id}/ownership-token {"target":"<host or bot>"}Issues a 24-hour proof token for a host (your domain) or a Telegram bot. Returns {"token","kind","target","expires_at"}; the token is in this answer only. Put it in https://<host>/.well-known/deneb-wallet.json ({"tokens":["<token>"]}) or in your bot's short description.
POST /api/account/wallets/{id}/ownership-verify {"target":"<host or bot>"}Reads the token back from the target and returns `{"result":"verified""not_found""unreadable"}. verified proves the target until a check finds the token gone (not_found); unreadable` changes nothing. Keep the token in place. A bot needs a short description to be checked.

A method is {"kind", "template", "modes", "delivery"}: kind is telegram_bot, telegram_app, domain or walletconnect (a marker, no other fields); modes are tx and/or session; delivery (bot or mini_app) is required with session. There is no publish endpoint: only a Deneb moderator publishes.

For WalletConnect and the prices API (ways 3 and 4), contact the Deneb team for now. Self-service API keys in the cabinet are planned.

What to tell us about your wallet:

  1. Where is the user's key kept: on your server (bot) or on the user's device (Mini App, app)? Who can sign with it?

  2. Does your wallet support WalletConnect v2 today?

  3. Which wrapped tokens do you use (tickers and coin ids on Minter), and which pools should be tradable for your users?