> ## Documentation Index
> Fetch the complete documentation index at: https://docs.totalis.trade/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication & signing

> Scoped API keys, the scopes each route needs, and the EIP-712 and EIP-3009 signatures that move funds.

```bash theme={null}
curl https://hip4-api.totalis.trade/v1/me \
  -H "Authorization: Bearer $TOTALIS_API_KEY"
```

A key authenticates the call. The vault contract only moves funds with a signature from the funds' owner,
sent in the request body. Market reads need no key and ignore one. Get deployment and the RFQ reads need no key
either, but an invalid, expired or revoked key on them returns `401`.

| Credential | For | Issued by |
| - | - | - |
| API key (`ttk_`) | A bot, script or maker acting for one account | The account's wallet: [Create, rotate, revoke](#create-rotate-revoke) |
| Wallet session | A maker managing its maker and keys headless. A user signing in with their own wallet on a partner's site. | Totalis, when the account's wallet signs a Sign-In with Ethereum message: [Sign in](https://docs.totalis.trade/hyperliquid/guides/market-making.md#set-up) for a maker, [Your users' own wallets](https://docs.totalis.trade/hyperliquid/build/partner-frontend.md#sessions) for a partner's user (a new account needs the partner's admission first) |
| Partner keys (`tpk_`, `tpb_`) | A partner's server and pages | Totalis, by email: [Build on Totalis](https://docs.totalis.trade/hyperliquid/build/overview.md#get-access) |

## Keys

This section and the next are about API keys (`ttk_`). There is one kind. Each key acts for one account, yours or a maker's, and holds only scopes
that account can use.

| Account | Approved by | Signs trades | Reads |
| - | - | - | - |
| Yours | Your account's wallet | Your account's wallet (`wallet` in [Get identity](https://docs.totalis.trade/hyperliquid/api-reference/account/get-identity.md)) | `/v1/me/...` |
| A maker (`maker_id`) | The maker wallet | The maker wallet (`signer` in [Get maker capital](https://docs.totalis.trade/hyperliquid/api-reference/makers/get-maker-capital.md)) | `/v1/me/positions`, `/v1/me/activity` and `/v1/me/operations` for the maker, plus the [maker routes](#maker-routes) |

* The key alone selects the account, chain and vault. No header or parameter does.
* A key for a maker naming another `maker_id` gets `404`.
* Keys start with `ttk_v1_prd_`, or `ttk_v1_stg_` on [Staging](https://docs.totalis.trade/hyperliquid/build/staging.md).

### Maker routes

A maker key calls these, each with the scope in [Scopes](#scopes):

| Route | Scope |
| - | - |
| [Get maker capital](https://docs.totalis.trade/hyperliquid/api-reference/makers/get-maker-capital.md), [Get maker withdrawal](https://docs.totalis.trade/hyperliquid/api-reference/makers/get-maker-withdrawal.md), [Get collateral reduction](https://docs.totalis.trade/hyperliquid/api-reference/makers/get-collateral-reduction.md), [List quote history](https://docs.totalis.trade/hyperliquid/api-reference/makers/list-quote-history.md) | `vault:read` |
| [List acceptances](https://docs.totalis.trade/hyperliquid/api-reference/quotes/list-acceptances.md) | `quote:read` |
| [Create quote](https://docs.totalis.trade/hyperliquid/api-reference/quotes/create-quote.md), [Cancel quote](https://docs.totalis.trade/hyperliquid/api-reference/quotes/cancel-quote.md), [Confirm quote](https://docs.totalis.trade/hyperliquid/api-reference/quotes/confirm-quote.md), [Keep quote lease](https://docs.totalis.trade/hyperliquid/api-reference/quotes/keep-quote-lease.md), [Release quote lease](https://docs.totalis.trade/hyperliquid/api-reference/quotes/release-quote-lease.md) | `quote:write` |
| [Create collateral reduction](https://docs.totalis.trade/hyperliquid/api-reference/makers/create-collateral-reduction.md) | `vault:write` |
| [Submit self-funded transaction](https://docs.totalis.trade/hyperliquid/api-reference/makers/submit-self-funded-transaction.md) | `operations:submit` |

A maker key reads `/v1/me/positions`, `/v1/me/activity`, `/v1/me/operations` and its capital only if it holds
`vault:read`. Totalis grants nothing else.

The maker's position, exposure, performance and activity pages in the app read `/v1/makers/{maker_id}/...`
routes that only the app's session can call. A maker key gets `403` on them.

## Create, rotate, revoke

The account's wallet approves every API key.

| Keys for | Managed |
| - | - |
| Your account, created in the Totalis app | In the app, or headless like a maker's |
| A maker | Headless only, from a wallet session with the SDK or the API: [Manage keys](https://docs.totalis.trade/hyperliquid/guides/market-making.md#manage-keys). The app lists them read-only. |
| An account whose own wallet signs in on a partner's site | From its wallet session with the SDK's `totalis.issueApiKey` and `rotateApiKey` ([SDK](https://docs.totalis.trade/hyperliquid/sdk/wallets.md#issue-a-key-from-a-session)), or in the partner's own UI |

In the [Totalis app](https://hip4.totalis.trade/account/api-keys), under Account, then API keys:

1. Enter a name, the [scopes](#scopes) and an expiry: 1, 7, 30 or 90 days, or Forever. Only your
   account's scopes are offered.
2. Your wallet approves with a Sign-In with Ethereum message.
3. Copy the key. It is shown once.

Rotating takes the same approval and keeps the name and scopes. The old key can overlap for none, one
hour or 24 hours. Revoking needs no signature and takes effect at once. If a create or rotate retry
returns `SECRET_UNAVAILABLE`, the secret was issued and cannot be shown again: revoke that key and create another. An API key cannot create, rotate or revoke
keys.

Outside the app, the approval is three calls: a key approval challenge, the wallet's `personal_sign` of its
Sign-In with Ethereum message, then the create or rotate call with that proof. They need a wallet session or an
app session from an allowed origin, never an API key. Through the API, `expires_in_days` is 1 to 90, or 0 for no
expiry (30 when omitted), and `overlap_seconds` is 0 to 86400 (3600 when omitted).

| Step | Your account | A maker |
| - | - | - |
| Challenge | [Create API key challenge](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/create-api-key-challenge.md) | [Create maker API key challenge](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/create-maker-api-key-challenge.md) |
| Create or rotate | [Create API key](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/create-api-key.md), [Rotate API key](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/rotate-api-key.md) | [Create maker API key](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/create-maker-api-key.md), [Rotate maker API key](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/rotate-maker-api-key.md) |
| List, revoke | [List API keys](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/list-api-keys.md), [Revoke API key](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/revoke-api-key.md) | [List maker API keys](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/list-maker-api-keys.md), [Revoke maker API key](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/revoke-maker-api-key.md) |
| Scopes you can issue | [List API key scopes](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/list-api-key-scopes.md) | [List maker API key scopes](https://docs.totalis.trade/hyperliquid/api-reference/api-keys/list-maker-api-key-scopes.md) |

## Scopes

| Scope | Account | Grants |
| - | - | - |
| `identity:read` | Yours | Your identity and wallet |
| `account:read` | Yours | Balances, positions, activity, operations, withdrawals |
| `account:stream` | Yours | The [account channel](https://docs.totalis.trade/hyperliquid/api-reference/websocket/account.md) |
| `rfq:read` | Either | Open RFQs and RFQ events |
| `rfq:write` | Yours | Create and cancel RFQs |
| `quote:read` | Either | Yours: quotes on your RFQs, your acceptances. A maker: acceptances of its quotes. |
| `quote:accept` | Yours | Accept a quote |
| `position:cashout` | Yours | Accept a cash-out quote |
| `funding:deposit` | Yours | Fund an accept's shortfall from your wallet |
| `funding:withdraw` | Yours | Withdraw |
| `sponsorship:use` | Yours | Required on every accept and cash-out made with an API key, and on withdrawals. Totalis relays them and pays the gas. |
| `quote:write` | Maker | Create, cancel and confirm quotes |
| `replay:read` | Either | Resume the WebSocket from a cursor |
| `vault:read` | Maker | Capital, positions, activity, operations, collateral reductions |
| `vault:write` | Maker | Request a collateral reduction |
| `operations:submit` | Maker | Submit a self-funded transaction |

| Integration | Account | Scopes |
| - | - | - |
| Taker | Yours | `identity:read`, `account:read`, `account:stream`, `replay:read`, `rfq:write`, `quote:read`, `quote:accept`, `position:cashout`, `sponsorship:use`, `funding:deposit` |
| Taker that withdraws | Yours | The taker scopes plus `funding:withdraw` |
| Maker | The maker | `rfq:read`, `quote:read`, `quote:write`, `replay:read`, `vault:read` |
| Maker collateral | The maker | `vault:read`, `vault:write`, `operations:submit` |

Any active maker can issue both maker scope sets from its wallet session: `QUOTING_BOT_SCOPES` and `COLLATERAL_SCOPES`
in the SDK ([Manage keys](https://docs.totalis.trade/hyperliquid/guides/market-making.md#manage-keys)).

## Wallet key

If your account signs in with its own wallet, you already hold that wallet's private key. For an account created in the Totalis app, the wallet
is embedded in the app. To sign from code, export its key once in a browser: Account, then Private key, then
**Export private key**. A maker needs it for everything after signup. Check its address equals `wallet` in `GET /v1/me`, or for a maker, `signer` in
[Get maker capital](https://docs.totalis.trade/hyperliquid/api-reference/makers/get-maker-capital.md). A maker key cannot call `GET /v1/me`.

> [!WARNING]
>
> The exported key also signs withdrawals. Anyone who has it can withdraw everything the account holds.
> Keep only the balance your bot needs.

A maker is one wallet too. Its bot signs confirmations with that wallet's key, the same key that funds
and withdraws the maker. Anyone who has it controls the maker, so keep only the collateral your bot needs.
A maker cannot move to another wallet: see [Your maker wallet](https://docs.totalis.trade/hyperliquid/guides/market-making.md#your-maker-wallet)
and [Move maker funds](https://docs.totalis.trade/hyperliquid/guides/collateral.md#move-maker-funds).

## Who signs what

| Action | Signer | Message | Body field |
| - | - | - | - |
| Accept an entry quote | Your wallet | `TakerAccept` | `taker_signature` |
| Accept a cash-out quote | The owner | `SellBack` or `CashoutTransfer` | `taker_signature` |
| Confirm an entry quote | The maker wallet | `Quote` | `maker_signature` |
| Confirm a cash-out quote | The maker wallet | `SellBack` or `CashoutTransfer` | `maker_signature` |
| Fund an accept | Your wallet | USDC `ReceiveWithAuthorization` | `funding.authorization_signature` |
| Bridge USDC from HyperCore into an entry | Your wallet | `HyperliquidTransaction:SendAsset` | None. Sent to Hyperliquid after the maker confirms, before the acceptance's `fund_by`. |
| Deposit | Your wallet | USDC `ReceiveWithAuthorization` | [Create deposit](https://docs.totalis.trade/hyperliquid/api-reference/deposits/create-deposit.md) body (wallet session only) |
| Withdraw: vault shortfall | Your wallet | `Exit` | `vault_withdrawal.signature` |
| Withdraw: payout | Your wallet | USDC `TransferWithAuthorization` | `payout_authorization.authorization_signature` |

Settling and claiming need no signature. Send signatures as lowercase hex with `v` of 27 or 28. EOA and
ERC-1271 signatures are accepted.

## Domain

Read [Get deployment](https://docs.totalis.trade/hyperliquid/api-reference/deployment/get-deployment.md) before you sign; re-read the
fees before each quote.

```json theme={null}
{
  "chain_id": "999",
  "vault_address": "0x0cbffe7b40b64d5fd04f1288f4c9fe0fc50e2f83",
  "fee_bps": 100,
  "taker_fee_bps": 150,
  "usdc": {
    "address": "0xb88339cb7199b77e23db6e890353e22632ba630f",
    "eip712_domain": { "name": "USDC", "version": "2", "chain_id": "999", "verifying_contract": "0xb88339cb7199b77e23db6e890353e22632ba630f" }
  }
}
```

| Messages | EIP-712 domain |
| - | - |
| `Quote`, `TakerAccept`, `SellBack`, `CashoutTransfer`, `Exit` | `{ name: "TotalisParlay", version: "1", chainId: chain_id, verifyingContract: vault_address }` |
| `ReceiveWithAuthorization`, `TransferWithAuthorization` | `usdc.eip712_domain` |
| `HyperliquidTransaction:SendAsset`, the HyperCore bridge into an entry | `{ name: "HyperliquidSignTransaction", version: "1", chainId: chain_id, verifyingContract: "0x0000000000000000000000000000000000000000" }` |

## Types

```text theme={null}
Quote(uint64 makerId,Leg[] legs,uint128 stake,uint128 payout,uint16 feeBps,uint16 takerFeeBps,address taker,uint64 expiry,uint256 salt)
TakerAccept(uint64 makerId,Leg[] legs,uint128 stake,uint128 payout,uint16 feeBps,uint16 takerFeeBps,address taker,uint64 expiry,uint256 salt)
Leg(uint32 outcomeId,uint8 side)
SellBack(bytes32 ticketId,uint128 price,address owner,uint64 expiry,uint256 salt,bytes32 legState)
CashoutTransfer(bytes32 ticketId,uint128 price,address seller,address buyer,uint64 expiry,uint256 salt,bytes32 legState)
Exit(address account,address to,uint128 amount,uint64 expiry,uint256 salt)
ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)
TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)
HyperliquidTransaction:SendAsset(string hyperliquidChain,string destination,string sourceDex,string destinationDex,string token,string amount,string fromSubAccount,uint64 nonce)
```

## API names and signed names

Signed field names differ from the API's. This is the only place they do.

| API | Signed |
| - | - |
| `position_id` | `ticketId` |
| `entry` terms | `Quote` and `TakerAccept` |
| `sell_back`, `transfer`, `vault_withdrawal` | `SellBack`, `CashoutTransfer`, `Exit` |
| `quote_id` | The EIP-712 digest of the quote's terms. For an entry quote it is also the new `position_id`. |
| Leg `side`: `YES`, `NO` | `side`: `0`, `1` |
| `maker_id`, `fee_bps`, `taker_fee_bps`, `leg_state`, `outcome_id` | `makerId`, `feeBps`, `takerFeeBps`, `legState`, `outcomeId` |

## USDC nonces

| Authorization | Nonce |
| - | - |
| Accept funding | `keccak256(abi.encode(vault, chainId, from, salt, account))`, with `from` and `account` your wallet. Send `salt`, not the nonce. |
| Withdrawal payout | `keccak256(abi.encode(keccak256("TOTALIS_PAYOUT_NONCE_V1"), chainId, vault, account, uint128(Idempotency-Key)))`. Not sent. |

Signature windows are on [Limits](https://docs.totalis.trade/hyperliquid/limits-and-fees.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.