---
name: Hubra
description: Use when building integrations that stake SOL, mint liquid staking tokens (raSOL), deposit into leveraged strategies (raSOL Max), or earn yield on USDC. Reach for this skill when agents need to build unsigned Solana transactions, sign them locally, and broadcast them to the Solana blockchain through Hubra's endpoints.
metadata:
    mintlify-proj: hubra
    version: "1.0"
---

# Hubra Agent API Skill

## Product summary

Hubra is a Solana staking and yield platform with an HTTP API designed for agents. The API mirrors the human app's functionality: agents call REST endpoints to build unsigned Solana transactions, sign them locally with their own keypair, and broadcast them back. No API keys, no sign-up, no database — authorization comes from the on-chain signature itself. Base URL: `https://hubra.app/api/v1`. Four canonical strategies are live: `sol-native-stake` (direct delegation), `sol-liquid-stake` (mint raSOL), `sol-leveraged-stake` (raSOL Max), and `usdc-earn` (USDC vault). All amounts are decimal strings, not floats. Errors follow RFC 9457 problem-details format. See [developer/overview](https://docs.hubra.app/developer/overview) for the full API reference.

## When to use

Reach for this skill when:

- **Staking SOL**: An agent needs to stake SOL into one of three strategies (native delegation, liquid raSOL, or leveraged raSOL Max).
- **Unstaking or withdrawing**: An agent needs to exit a position — deactivate a native stake, swap raSOL to SOL, or burn raSOL Max LP.
- **Earning yield on USDC**: An agent needs to deposit USDC into the Voltr-routed vault.
- **Previewing transactions**: An agent needs to quote an unstake to show price impact and output amount before signing.
- **Building integrations**: An agent is building a protocol, bot, or app that needs to interact with Hubra's staking infrastructure.

Do not use this skill for: wallet management, token swaps outside of staking/unstaking, or operations that don't involve Hubra's four strategies.

## Quick reference

### Strategy keys and assets

| Key | Asset in | Asset out | Route | Status |
| --- | --- | --- | --- | --- |
| `sol-native-stake` | SOL | None (stake account) | Native delegation | live |
| `sol-liquid-stake` | SOL | raSOL | Sanctum | live |
| `sol-leveraged-stake` | SOL | raSOL Max LP | Voltr | live |
| `usdc-earn` | USDC | raUSDC | Voltr | live |

### Core endpoints

| Endpoint | Method | Purpose |
| --- | --- | --- |
| `/strategies` | GET | List all strategies with live APY and exchange rates |
| `/strategies/{key}` | GET | Get detailed info on a single strategy |
| `/stake` | POST | Build an unsigned stake transaction |
| `/unstake` | POST | Build an unsigned unstake transaction |
| `/quote` | POST | Preview unstake output and price impact |
| `/withdraw` | POST | Complete a native stake deactivation (after epoch) |
| `/broadcast` | POST | Submit a signed transaction |
| `/health` | GET | Check API health |
| `/apy/history` | GET | Get time-series APY data |

### Request/response conventions

- **Content-Type**: `application/json` for requests and success; `application/problem+json` for errors (RFC 9457).
- **Amounts**: Always decimal strings (`"1.5"`), never floats. Precision is preserved server-side.
- **Versioning**: All endpoints under `/api/v1`. Breaking changes ship as `/api/v2`. Response header: `X-Hubra-Api-Version: v1`.
- **CORS**: Read endpoints accept any origin. Write endpoints accept the same.
- **Rate limiting**: Currently none. High-volume callers should contact `hello@hubra.app`.

### Required fields by endpoint

**POST /stake:**
- `strategy` (required): one of the four keys
- `wallet` (required): Solana pubkey (base58)
- `amount` (required): decimal string
- `referral_code` (optional): attribution code

**POST /unstake:**
- `strategy` (required)
- `wallet` (required)
- `kind` (required): `"deactivate"`, `"instant"`, or `"slow"` (varies by strategy)
- `amount` (conditional): required except for `usdc-earn` with `isWithdrawAll: true`
- `stakeAccount` (conditional): required for `sol-native-stake`

**POST /quote:**
- `strategy` (required)
- `wallet` (required)
- `amount` (required)
- `stakeAccount` (conditional): required for `sol-native-stake`

**POST /broadcast:**
- `signed_tx` (required): base64-encoded signed transaction
- `hubra_token` (required): HMAC token from `/stake` or `/unstake`
- `route` (optional): `"rpc"` (default) or `"sanctum"` for swap flows
- `sanctumKind` (conditional): required when `route="sanctum"`
- `sanctum_order` (conditional): required when `route="sanctum"`

## Decision guidance

### When to use each staking strategy

| Goal | Strategy | Why | Unstake options |
| --- | --- | --- | --- |
| Direct validator delegation, no receipt token | `sol-native-stake` | Simplest, no smart contract risk | Deactivate (epoch-bound) or instant via Sanctum |
| Earn staking yield + stay liquid | `sol-liquid-stake` | Mint raSOL, use in DeFi, swap anytime | Instant (Sanctum swap) or slow (convert to stake account) |
| Amplified staking yield, auto-managed leverage | `sol-leveraged-stake` | raSOL Max handles leverage automatically | Instant (burn LP → raSOL, optionally chain to SOL) |
| Earn yield on stablecoins | `usdc-earn` | Voltr vault, no lockup | Instant (direct withdraw) |

### When to use `route: "sanctum"` vs `route: "rpc"` at broadcast

| You came from | Use | Why |
| --- | --- | --- |
| `/stake sol-liquid-stake` | `route: "sanctum"` | Sanctum's MEV protection and smarter retries |
| `/stake sol-native-stake` | `route: "rpc"` | No swap involved; plain RPC is fine |
| `/unstake sol-liquid-stake instant` | `route: "sanctum"` | Sanctum swap; forward `sanctumKind` and `sanctum_order` |
| `/unstake sol-native-stake instant` | `route: "sanctum"` | Sanctum's `depositStake` route; forward Sanctum fields |
| `/unstake sol-native-stake deactivate` | `route: "rpc"` | Standard epoch deactivation; no swap |
| `/unstake usdc-earn instant` | `route: "rpc"` | Voltr direct withdraw; no Sanctum involvement |

### When to rebuild vs retry

| Error | Rebuild? | Retry? | Action |
| --- | --- | --- | --- |
| `400 invalid_request` | No | No | Fix the request body |
| `403 forbidden` (hubra_token) | Yes | Yes | Rebuild `/stake` or `/unstake`, sign, broadcast with new token |
| `404 not_found` | No | No | Fix the strategy key or referral code |
| `502 upstream_error` | No | Yes | Exponential backoff, 3 retries max |
| `503 service_unavailable` | No | Yes | Honor `Retry-After` header |

## Workflow

### Typical staking flow

1. **Discover strategies**: Call `GET /api/v1/strategies` to list all available strategies and their live APY.

2. **Choose a strategy**: Pick one of the four keys based on the user's goal (native staking, liquid staking, leveraged, or USDC yield).

3. **Build the transaction**: Call `POST /api/v1/stake` with the strategy key, wallet pubkey, and amount (decimal string). Save the returned `transaction` (base64), `hubra_token`, and any Sanctum-specific fields (`sanctumKind`, `sanctum_order`).

4. **Sign locally**: Deserialize the base64 transaction, sign it with the wallet's keypair using `@solana/web3.js` or equivalent. For `sol-native-stake`, the stake-account slot is pre-signed; only sign the wallet slot.

5. **Broadcast**: Call `POST /api/v1/broadcast` with the signed transaction (base64), `hubra_token`, and route metadata. If the build response had `route: "sanctum"`, forward `sanctumKind` and `sanctum_order`.

6. **Confirm**: The response includes the on-chain signature and a Solscan link. Poll the chain or wait for confirmation.

7. **Track the position**: For `sol-native-stake`, save the returned `stakeAccount` pubkey — you need it for future unstakes or withdrawals.

### Typical unstaking flow

1. **Preview (optional)**: Call `POST /api/v1/quote` with the strategy, wallet, and amount to see the output and price impact.

2. **Build the unstake**: Call `POST /api/v1/unstake` with the strategy, wallet, amount, and `kind` (varies by strategy). For `sol-native-stake`, include the `stakeAccount` pubkey from the original stake.

3. **Sign and broadcast**: Same as staking — deserialize, sign, call `/broadcast` with the token and route metadata.

4. **Handle multi-step exits**: For `sol-leveraged-stake` with `outputAsset: "SOL"`, the response includes a `next` step. Broadcast the first tx, read the actual raSOL received, then call the `next` endpoint with that real amount.

5. **Complete native deactivation**: For `sol-native-stake deactivate`, wait ~2.5 days for the epoch to pass, then call `POST /api/v1/withdraw` to close the stake account and pull SOL back.

## Common gotchas

- **Decimal strings, not floats**: Always pass amounts as `"1.5"`, not `1.5`. The server parses with full precision; floats lose precision.

- **hubra_token expires in ~2 minutes**: If you don't broadcast within 2 minutes of building, the token expires (matching Solana's blockhash window). Rebuild via `/stake` or `/unstake` to get a fresh token.

- **Sanctum fields are required for swap flows**: If the build response has `route: "sanctum"`, you must forward `sanctumKind` and `sanctum_order` to `/broadcast`. Without them, Sanctum rejects the broadcast.

- **Save stakeAccount for native staking**: The `/stake` response for `sol-native-stake` returns a new `stakeAccount` pubkey. Save it — you need it for every future unstake or withdraw on that position.

- **sol-leveraged-stake deposits SOL, not raSOL**: The API takes SOL as input and handles the SOL → raSOL → raSOL Max LP conversion in one atomic transaction. There is no "deposit raSOL directly" variant.

- **sol-leveraged-stake unstake stops at raSOL**: Burning raSOL Max LP returns raSOL, not SOL. To finish to SOL, pass `outputAsset: "SOL"` and handle the two-step flow (broadcast first tx, read actual raSOL, then call the `next` endpoint).

- **Branch on error `type`, not `title`**: The `type` slug is stable; `title` is human-friendly and may change. Use `type` for error handling logic.

- **No quote for deposits**: There is no quote endpoint for staking into a strategy. Deposit quotes are deterministic — read the exchange rate from `GET /api/v1/strategies/{key}` and compute locally.

- **Referral codes are optional but first-write-wins**: Pass a `referral_code` on `/stake` to attribute the wallet to a referrer. The first referrer to bring a wallet in keeps the credit; a wallet is never credited to itself.

- **Idempotency key for retries**: Pass `Idempotency-Key: <uuid>` on write endpoints to replay the same response within 24 hours if a network blip causes a retry.

## Verification checklist

Before submitting work:

- [ ] All amounts are decimal strings (`"1.5"`), not floats.
- [ ] For `sol-native-stake`, the `stakeAccount` from the original stake is saved and used in unstake/withdraw calls.
- [ ] For Sanctum-routed flows, `sanctumKind` and `sanctum_order` are forwarded to `/broadcast`.
- [ ] The `hubra_token` is passed to `/broadcast` and matches the transaction being signed.
- [ ] For `sol-leveraged-stake` with `outputAsset: "SOL"`, the two-step flow is handled (broadcast first, read actual raSOL, then call `next`).
- [ ] Error handling branches on `type` slug, not `title`.
- [ ] Retry logic respects `Retry-After` headers and uses exponential backoff for transient errors.
- [ ] For `sol-native-stake deactivate`, the workflow includes a `/withdraw` call after the epoch passes.
- [ ] The wallet pubkey is valid base58 and funded with at least the amount to stake plus a few thousand lamports for safety.

## Resources

- **Comprehensive API navigation**: [https://docs.hubra.app/llms.txt](https://docs.hubra.app/llms.txt) — page-by-page listing of all documentation.
- **Developer overview**: [https://docs.hubra.app/developer/overview](https://docs.hubra.app/developer/overview) — architecture, auth model, and end-to-end flow.
- **Strategies reference**: [https://docs.hubra.app/developer/strategies](https://docs.hubra.app/developer/strategies) — detailed mechanics of all four strategies, including stake/unstake paths and live data.
- **Errors and troubleshooting**: [https://docs.hubra.app/developer/errors](https://docs.hubra.app/developer/errors) — error slugs, retry policy, and common failure modes.

---

> For additional documentation and navigation, see: https://docs.hubra.app/llms.txt