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

# POST /stake

> Build a Solana transaction that stakes the strategy's input asset. Returns base64 unsigned (or partially signed) bytes.

```http theme={null}
POST https://hubra.app/api/v1/stake
```

Build a Solana transaction that stakes `amount` of the strategy's input asset. The returned `transaction` is **base64-encoded**:

* **Unsigned** for `sol-liquid-stake`, `sol-leveraged-stake`, and `usdc-earn`.
* **Partially signed** for `sol-native-stake` (the stake-account slot is pre-signed by the server; you only sign the wallet slot).

The agent signs locally and broadcasts via [`POST /api/v1/broadcast`](/developer/endpoints/broadcast).

***

## Request

```bash theme={null}
curl -X POST https://hubra.app/api/v1/stake \
  -H 'Content-Type: application/json' \
  -d '{
    "strategy": "sol-liquid-stake",
    "wallet":   "<your-wallet>",
    "amount":   "1.5"
  }'
```

| Field             | Type                                                                               | Required | Description                                                                                                                                                                                                                                                |
| ----------------- | ---------------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `strategy`        | `"sol-native-stake" \| "sol-liquid-stake" \| "sol-leveraged-stake" \| "usdc-earn"` | yes      | Which strategy to stake into.                                                                                                                                                                                                                              |
| `wallet`          | `string`                                                                           | yes      | Solana wallet pubkey (base58) that will sign the transaction.                                                                                                                                                                                              |
| `amount`          | `string`                                                                           | yes      | Amount to stake, decimal string. The input asset is the strategy's `asset` — **SOL** for the three `sol-*` keys (including `sol-leveraged-stake`), USDC for `usdc-earn`.                                                                                   |
| `partner_api_key` | `string`                                                                           | no       | Your partner API key from [partner.hubra.app](https://partner.hubra.app). Credits the wallet you bring in to your partner account. Can also be sent as the `X-Partner-Key` header instead of in the body. See [Partner attribution](#partner-attribution). |

***

## Partner attribution

If you're a Hubra **partner** (protocol, dev, or creator), pass your partner API key on each stake call and the wallet you bring in is attributed to you — the resulting liquidity shows up on your [partner dashboard](https://partner.hubra.app).

Get your key from [partner.hubra.app](https://partner.hubra.app) → **Dashboard → API key**. Send it either as a body field or a header:

```bash theme={null}
# As a body field
curl -X POST https://hubra.app/api/v1/stake \
  -H 'Content-Type: application/json' \
  -d '{
    "strategy":        "sol-liquid-stake",
    "wallet":          "<end-user-wallet>",
    "amount":          "1.5",
    "partner_api_key": "hbr_pk_<your-key>"
  }'

# …or as a header (keeps the key out of the JSON body)
curl -X POST https://hubra.app/api/v1/stake \
  -H 'Content-Type: application/json' \
  -H 'X-Partner-Key: hbr_pk_<your-key>' \
  -d '{"strategy":"sol-liquid-stake","wallet":"<end-user-wallet>","amount":"1.5"}'
```

<Info>
  Attribution is **first-write-wins** per wallet: the first partner to bring a wallet in keeps the credit. Passing the key is optional — omit it and the stake behaves exactly as before. If you pass a key that is unknown or belongs to an inactive partner, the call returns `403 forbidden` so you notice rather than silently losing attribution.
</Info>

<Warning>
  Treat the partner API key like a secret — it identifies your partner account. Prefer the `X-Partner-Key` header in server-side integrations, and rotate the key from your dashboard if it leaks.
</Warning>

***

## Response — `sol-native-stake`

The server generates a fresh stake-account keypair and pre-signs that signature slot. The agent only signs as the wallet. **Save the returned `stakeAccount` pubkey** — you need it for future deactivate / withdraw / instant-unstake calls against this position.

```json theme={null}
{
  "strategy":                  "sol-native-stake",
  "transaction":               "<base64 partially-signed tx>",
  "hubra_token":               "<token to pass to /broadcast>",
  "stakeAccount":              "<new pubkey to track>",
  "voteAccount":               "7K8DVxtNJGnMtUY1CQJT5jcs8sFGSZTDiG7kowvFpECh",
  "rentExemptReserveLamports": 2282880,
  "delegatedLamports":         1500000000,
  "signers":                   ["<your-wallet>"],
  "notes":                     "Stake account keypair was generated and pre-signed server-side."
}
```

Broadcast via `route: "rpc"` (no Sanctum involvement on the create + delegate path).

***

## Response — `sol-liquid-stake` (Sanctum-routed)

```json theme={null}
{
  "strategy":      "sol-liquid-stake",
  "transaction":   "<base64 unsigned tx>",
  "hubra_token":   "<token to pass to /broadcast>",
  "route":         "sanctum",
  "sanctumKind":   "token",
  "sanctum_order": { "...": "..." },
  "signers":       ["<your-wallet>"]
}
```

When `route: "sanctum"`, the response also carries `sanctumKind` and `sanctum_order`. **All three (`hubra_token`, `sanctumKind`, `sanctum_order`) must be passed back to `/broadcast`** if you want Sanctum's MEV-protected broadcaster. Sanctum's execute endpoint validates the signed transaction against the original order and rejects mismatches.

Plain RPC (`route: "rpc"` at broadcast) works without the Sanctum-specific fields, but loses Sanctum's broadcaster guarantees.

***

## Response — `usdc-earn` (Voltr-routed)

```json theme={null}
{
  "strategy":    "usdc-earn",
  "transaction": "<base64 unsigned tx>",
  "hubra_token": "<token to pass to /broadcast>",
  "route":       "voltr",
  "signers":     ["<your-wallet>"]
}
```

Voltr-routed responses do not include `sanctum_order`. Broadcast via `route: "rpc"` — that is the only supported broadcast path for Voltr transactions.

***

## Response — `sol-leveraged-stake` (raSOL Max)

`amount` is **SOL**. The server builds a **single transaction** that does the whole conversion: create the raSOL ATA (idempotent) → SPL stake-pool `DepositSol` (SOL → raSOL) → Voltr `depositVault` (raSOL → raSOL Max LP). One signature, atomic.

```json theme={null}
{
  "strategy":             "sol-leveraged-stake",
  "transaction":          "<base64 unsigned tx>",
  "hubra_token":          "<token to pass to /broadcast>",
  "route":                "rpc",
  "depositedSolLamports": "20000000",
  "stagedRasolLamports":  "16700000",
  "receiptMint":          "CJEYakpjmKBvvUzAn3HJSs9vtijnv472T8YJEV3WzToF",
  "receiptSymbol":        "raSOL Max",
  "signers":              ["<your-wallet>"]
}
```

Broadcast via `route: "rpc"` — no Sanctum or Voltr execute leg. After it confirms, read your raSOL Max LP balance on-chain; you pass that figure to [`POST /api/v1/unstake`](/developer/endpoints/unstake) to burn the position later.

<Info>
  The API deposits **SOL only** — the SOL → raSOL leg is built in for you. There is no "deposit raSOL directly" variant on the agent surface. The Voltr leg is sized from the exact raSOL the stake-pool mint produces (the same floor-rounded `lamports × supply / total_lamports` the pool applies on-chain), so the staged raSOL always matches what the deposit instruction expects.
</Info>

***

## The `hubra_token`

Every `/stake` (and `/unstake`) response includes a `hubra_token` HMAC'd over the message bytes of the unsigned transaction. `POST /api/v1/broadcast` requires this token and rejects any transaction that was not built by Hubra. **Save it alongside the transaction and pass it back when broadcasting.**

Tokens expire \~2 minutes after issue (matching Solana's blockhash window). If your token expires, rebuild via `/stake`.

For the full mechanics, see [Hubra token](/developer/hubra-token).

***

## Examples

```bash theme={null}
# Native delegation to Hubra's validator
curl -X POST https://hubra.app/api/v1/stake \
  -H 'Content-Type: application/json' \
  -d '{"strategy":"sol-native-stake","wallet":"<your-wallet>","amount":"1.0"}'

# Liquid: SOL → raSOL via Sanctum
curl -X POST https://hubra.app/api/v1/stake \
  -H 'Content-Type: application/json' \
  -d '{"strategy":"sol-liquid-stake","wallet":"<your-wallet>","amount":"1.0"}'

# Leveraged: SOL → raSOL → raSOL Max in one tx
curl -X POST https://hubra.app/api/v1/stake \
  -H 'Content-Type: application/json' \
  -d '{"strategy":"sol-leveraged-stake","wallet":"<your-wallet>","amount":"1.0"}'

# USDC vault deposit
curl -X POST https://hubra.app/api/v1/stake \
  -H 'Content-Type: application/json' \
  -d '{"strategy":"usdc-earn","wallet":"<your-wallet>","amount":"100"}'
```

***

## Errors

| Status | Slug                  | When                                                                                                                                            |
| ------ | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | `invalid_request`     | Missing or malformed fields.                                                                                                                    |
| `403`  | `forbidden`           | `partner_api_key` (or `X-Partner-Key`) was supplied but is unknown or belongs to an inactive partner.                                           |
| `404`  | `not_found`           | Unknown strategy key.                                                                                                                           |
| `502`  | `upstream_error`      | Sanctum / Voltr could not build the transaction (wallet does not exist on-chain, no associated token account, insufficient liquidity for size). |
| `503`  | `service_unavailable` | Strategy is announced but not live.                                                                                                             |

***

## See also

<CardGroup cols={2}>
  <Card title="POST /unstake" icon="rotate-left" href="/developer/endpoints/unstake">
    Reverse the position.
  </Card>

  <Card title="POST /broadcast" icon="paper-plane" href="/developer/endpoints/broadcast">
    Submit the signed transaction.
  </Card>

  <Card title="Hubra token" icon="lock" href="/developer/hubra-token">
    The HMAC gate.
  </Card>

  <Card title="Strategies" icon="layer-group" href="/developer/strategies">
    All strategy keys.
  </Card>
</CardGroup>
