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

# Signing

> The signed message format required by each Vanish Core endpoint.

All endpoints take an `x-api-key` header, provisioned during onboarding. Everything below is about the signed message that goes with it.

***

## Signing Requests

Every endpoint except [`POST /commit`](/api-reference/commit) and [`POST /borrow/commit`](/api-reference/lending/commit) requires a signed message proving ownership of `user_address`. Sign with the user's Solana keypair (Ed25519) and base64-encode the result. Use the current Unix timestamp in milliseconds.

Every message shares the same prefix; only the `Details:` line changes:

```text theme={null}
By signing, I hereby agree to Vanish's Terms of Service and agree to be bound by them (docs.vanish.trade/legal/TOS)

Details: {details}
```

<Warning>
  The formats are not interchangeable. **The order of the values differs between them** - `timestamp` is second from last in the trade and lending formats, but last in the withdraw and settle formats - and two endpoints take the result as `signature` rather than `user_signature`. Check the exact format below for the endpoint you are calling.
</Warning>

| Format                                             | Used by                                                                                                                     | Pass as                                                                                          | Signature valid for |
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------- |
| [Read](#read-signing-format)                       | Account reads, [`/borrow/positions`](/api-reference/lending/positions), [`/borrow/pending`](/api-reference/lending/pending) | `signature` - except `user_signature` on [`/borrow/positions`](/api-reference/lending/positions) | 24 hours            |
| [Trade](#trade-signing-format)                     | [`POST /trade/create`](/api-reference/trade/create)                                                                         | `user_signature`                                                                                 | Current timestamp   |
| [Withdraw](#withdraw-signing-format)               | [`POST /withdraw/create`](/api-reference/funds/withdraw)                                                                    | `user_signature`                                                                                 | Current timestamp   |
| [One-Time Wallet](#one-time-wallet-signing-format) | [`POST /borrow/smart-wallet`](/api-reference/lending/smart-wallet)                                                          | `user_signature`                                                                                 | 10 minutes          |
| [Lending](#lending-signing-format)                 | [`POST /borrow/initiate`](/api-reference/lending/initiate)                                                                  | `user_signature`                                                                                 | 10 minutes          |
| [Settle](#settle-signing-format)                   | [`POST /borrow/settle`](/api-reference/lending/settle)                                                                      | `user_signature`                                                                                 | 10 minutes          |

### Read Signing Format

Used by [`/account/balances`](/api-reference/account/get_balances), [`/account/points`](/api-reference/account/get_points), [`/account/pending`](/api-reference/account/get_pending_actions), [`/borrow/pending`](/api-reference/lending/pending), and [`/borrow/positions`](/api-reference/lending/positions).

```text theme={null}
Details: read:{timestamp}
```

* Pass as `signature` - **except** on [`/borrow/positions`](/api-reference/lending/positions), which takes the same message as `user_signature`
* Accepted within 24 hours of the signed timestamp

### Trade Signing Format

Used by [`POST /trade/create`](/api-reference/trade/create).

```text theme={null}
Details: trade:{source_token_address}:{target_token_address}:{amount}:{loan_additional_sol}:{timestamp}:{jito_tip_amount}
```

* Pass as `user_signature`
* `timestamp` is second from last, before `jito_tip_amount`

### Withdraw Signing Format

Used by [`POST /withdraw/create`](/api-reference/funds/withdraw).

```text theme={null}
Details: withdraw:{token_address}:{amount}:{additional_sol}:{timestamp}
```

* Pass as `user_signature`
* `timestamp` is last

### One-Time Wallet Signing Format

Used by [`POST /borrow/smart-wallet`](/api-reference/lending/smart-wallet), which creates the one-time wallet a borrowing position lives in. Getting a wallet for a trade is unsigned - [`GET /trade/one-time-wallet`](/api-reference/trade/one-time-wallet) needs only the API key.

```text theme={null}
Details: borrow-smart-wallet:{protocol_label}:{timestamp}
```

* Pass as `user_signature`
* Valid for 10 minutes

### Lending Signing Format

Used by [`POST /borrow/initiate`](/api-reference/lending/initiate).

```text theme={null}
Details: borrow:{smart_wallet_id}:{source_token_address}:{amount}:{loan_additional_sol}:{timestamp}:{jito_tip_amount}
```

* Pass as `user_signature`
* Valid for 10 minutes
* Same value order as the trade format, with `smart_wallet_id` first: `timestamp` before `jito_tip_amount`

### Settle Signing Format

Used by [`POST /borrow/settle`](/api-reference/lending/settle).

```text theme={null}
Details: settle:{smart_wallet_id}:{token_address}:{amount}:{loan_additional_sol}:{cleanup_leftover_sol}:{timestamp}
```

* Pass as `user_signature`
* Valid for 10 minutes
* `timestamp` is **last** here, unlike the lending format, and there is no tip value
* `cleanup_leftover_sol` is rendered as it appears in the JSON body (`true` or `false`)

***

## Signing in Code

One helper covers every format - build the `Details:` line and pass it in.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import * as nacl from 'tweetnacl';
  import { Keypair } from '@solana/web3.js';

  const TOS = "By signing, I hereby agree to Vanish's Terms of Service and agree to be bound by them (docs.vanish.trade/legal/TOS)";

  function signMessage(details: string, keypair: Keypair): string {
    const message = [TOS, "", `Details: ${details}`].join('\n');
    const sig = nacl.sign.detached(new TextEncoder().encode(message), keypair.secretKey);
    return Buffer.from(sig).toString('base64');
  }

  // milliseconds, not seconds
  const timestamp = Date.now().toString();

  signMessage(`read:${timestamp}`, keypair);
  signMessage(`trade:${source}:${target}:${amount}:${loanSol}:${timestamp}:${jitoTip}`, keypair);
  signMessage(`withdraw:${token}:${amount}:${additionalSol}:${timestamp}`, keypair);
  signMessage(`borrow-smart-wallet:${protocolLabel}:${timestamp}`, keypair);
  signMessage(`borrow:${smartWalletId}:${source}:${amount}:${loanSol}:${timestamp}:${jitoTip}`, keypair);
  signMessage(`settle:${smartWalletId}:${token}:${amount}:${loanSol}:${cleanup}:${timestamp}`, keypair);
  ```

  ```rust Rust theme={null}
  use solana_sdk::signature::{Keypair, Signer};
  use base64::{engine::general_purpose, Engine as _};

  const TOS: &str = "By signing, I hereby agree to Vanish's Terms of Service and agree to be bound by them (docs.vanish.trade/legal/TOS)";

  fn sign_message(details: &str, keypair: &Keypair) -> String {
      let message = format!("{TOS}\n\nDetails: {details}");
      let sig = keypair.sign_message(message.as_bytes());
      general_purpose::STANDARD.encode(sig.as_ref())
  }

  // milliseconds, not seconds
  let timestamp = chrono::Utc::now().timestamp_millis().to_string();

  sign_message(&format!("read:{timestamp}"), &keypair);
  sign_message(&format!("trade:{source}:{target}:{amount}:{loan_sol}:{timestamp}:{jito_tip}"), &keypair);
  sign_message(&format!("withdraw:{token}:{amount}:{additional_sol}:{timestamp}"), &keypair);
  sign_message(&format!("borrow-smart-wallet:{protocol_label}:{timestamp}"), &keypair);
  sign_message(&format!("borrow:{smart_wallet_id}:{source}:{amount}:{loan_sol}:{timestamp}:{jito_tip}"), &keypair);
  sign_message(&format!("settle:{smart_wallet_id}:{token}:{amount}:{loan_sol}:{cleanup}:{timestamp}"), &keypair);
  ```
</CodeGroup>

<Info>
  Every value you sign must exactly match the value you send in the request body. On the lending endpoints, a timestamp outside its window is rejected with `400`, while a mismatched message or the wrong signing key returns `401` - see [Handling 401](/guide/handling#handling-401---signature-errors).
</Info>

***

## Next Steps

* [Trading](/guide/integration/trading) - Deposit, trade privately, and withdraw.
* [Lending](/guide/integration/lending) - Open a position, use the funds, then settle.
