> For the complete documentation index, see [llms.txt](https://docs.dimes.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.dimes.fi/for-developers/getting-started/quickstart.md).

# Quickstart

Start in [sandbox](/for-developers/getting-started/sandbox.md). Same API, same contract, test pUSD. Swap `api.dimes.fi` for `api-sandbox.dimes.fi` and use a `dm_sbx_skey_...` key — every example below works as-is. Working reference: [`dimes-demo-ui`](https://github.com/dimes-fi/dimes-demo-ui).

> **Using the SDK?** Install it: `npm install @dimes-dot-fi/sdk`. See [SDK Installation](/for-developers/getting-started/sdk-installation.md) for setup and peer dependencies. Every SDK snippet below has a runnable, type-checked counterpart in [`examples/`](https://github.com/dimes-fi/dimes-sdk/tree/main/examples) — start with [`01-quickstart.ts`](https://github.com/dimes-fi/dimes-sdk/blob/main/examples/01-quickstart.ts).

***

### 1. Authenticate

{% tabs %}
{% tab title="REST API" %}

```bash
curl -X POST https://api.dimes.fi/v1/prediction-markets/tokens \
  -H "Authorization: Api-Key dm_live_skey_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "wallet_address": "0x1234...abcd" }'
```

```json
{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "expires_at": "2026-04-16T11:00:00.000Z"
}
```

JWTs expire in 1 hour. Full details: [Authentication](/for-developers/api-and-events/authentication.md).
{% endtab %}

{% tab title="SDK" %}

```typescript
import { DimesClient, ApiKeyAuth } from "@dimes-dot-fi/sdk";

const client = new DimesClient({
  auth: new ApiKeyAuth({
    apiKey: process.env.DIMES_API_KEY,
    walletAddress: "0x1234...abcd",
  }),
});
```

`ApiKeyAuth` obtains and refreshes JWTs automatically. For client-side code with a JWT already in hand, use `JwtAuth` — see [SDK Installation](/for-developers/getting-started/sdk-installation.md).
{% endtab %}

{% tab title="React" %}

```tsx
import { DimesClient, JwtAuth } from "@dimes-dot-fi/sdk";
import { DimesProvider } from "@dimes-dot-fi/sdk/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const queryClient = new QueryClient();
const client = new DimesClient({
  auth: new JwtAuth({ tokenUrl: "https://your-backend.com/api/dimes-token" }),
});

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <DimesProvider client={client}>
        <YourApp />
      </DimesProvider>
    </QueryClientProvider>
  );
}
```

Hooks automatically use whatever `QueryClientProvider` is in your tree.
{% endtab %}
{% endtabs %}

***

### 2. List markets

{% tabs %}
{% tab title="REST API" %}

```bash
curl https://api.dimes.fi/v1/prediction-markets/markets
```

Each market includes `leverage.min_bps`, `max_bps`, and `step_bps` — clamp input to those. Full shape: [API Reference — Markets](/for-developers/api-and-events/api-reference.md#1-markets).
{% endtab %}

{% tab title="SDK" %}

```typescript
const { data: markets, hasMore } = await client.getMarkets();

for (const market of markets) {
  console.log(market.ticker, market.leverage.maxBps);
}
```

{% endtab %}

{% tab title="React" %}

```tsx
import { useMarkets } from "@dimes-dot-fi/sdk/react";

function MarketList() {
  const { data, isLoading } = useMarkets();

  if (isLoading) return <div>Loading...</div>;

  return (
    <ul>
      {data?.data.map((market) => (
        <li key={market.ticker}>{market.title}</li>
      ))}
    </ul>
  );
}
```

{% endtab %}
{% endtabs %}

***

### 3. Request a quote

{% tabs %}
{% tab title="REST API" %}

```bash
curl -X POST https://api.dimes.fi/v1/prediction-markets/quotes \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "market_ticker": "will-btc-hit-100k-2026",
    "effective_side": "yes",
    "leverage_bps": 50000,
    "notional_amount_usd_pips": "250000000",
    "slippage_bps": 300
  }'
```

The response carries pricing, fees, liquidation parameters, and a `contract_signature` for the on-chain call. Full shape and signature verification: [API Reference — Quotes](/for-developers/api-and-events/api-reference.md#3-quotes).

> **Draft + promote:** Quotes expire in 15 seconds. Call `/draft-quotes` first (no expiry), let the user review, then `/promoted-quotes/{draft_quote_id}` when they're ready. See [API Reference — Promote draft quote](/for-developers/api-and-events/api-reference.md#promote-draft-quote).
> {% endtab %}

{% tab title="SDK" %}

```typescript
import { executeQuote } from "@dimes-dot-fi/sdk";

const result = await executeQuote(client, {
  marketTicker: "will-btc-hit-100k-2026",
  side: "yes",
  collateralUsd: 25,
  leverageBps: 50000,
  slippageBps: 300,
});

console.log(result.quote.entryPriceUsd, result.quote.leverageBps);
```

`executeQuote` handles the draft → promote flow, retries on market-moved errors, and auto-corrects leverage/collateral/slippage when the API suggests adjustments.

Hook into each stage:

```typescript
const result = await executeQuote(client, params, {
  onDraftReady: (draft) => console.log("Draft:", draft.id),
  onMarketMoved: (event) => console.log("Retrying...", event.retryCount),
  onCorrection: (adj) => console.log("Adjusted:", adj.field, adj.toLabel),
});
```

{% endtab %}

{% tab title="React" %}

```tsx
import { useQuote } from "@dimes-dot-fi/sdk/react";

function QuoteButton({ marketTicker }: { marketTicker: string }) {
  const { state, execute, reset } = useQuote();

  const handleQuote = async () => {
    await execute({
      marketTicker,
      side: "yes",
      collateralUsd: 25,
      leverageBps: 50000,
      slippageBps: 300,
    });
  };

  return (
    <div>
      <button onClick={handleQuote} disabled={state.phase === "promoting"}>
        {state.phase === "idle" ? "Get Quote" : state.phase}
      </button>
      {state.quote && <div>Entry: {state.quote.entryPriceUsd}</div>}
    </div>
  );
}
```

`useQuote` manages the full state machine: `idle` → `loading-draft` → `draft-ready` → `promoting` → `promoted`.
{% endtab %}
{% endtabs %}

***

### 4. Open the position

Two on-chain calls: `pUSD.approve(vault, total_user_amount)` then `vault.createPosition(...)` with the quote parameters. After the tx confirms, Multiply acquires tokens, finalizes on-chain, and emits `position.opened`.

```
pending → open → closing → closed
           ↓
       liquidated
```

{% tabs %}
{% tab title="ethers.js" %}

```javascript
import { ethers } from "ethers";

const usdc = new ethers.Contract(USDC_ADDRESS, ["function approve(address,uint256)"], signer);
const approvalAmount = BigInt(quote.total_user_amount_usd_pips) * 100n;
await usdc.approve(quote.polygon_vault_contract_address, approvalAmount);

const VAULT_ABI = [
  "function createPosition(bytes16,bytes32,uint256,uint256,uint32,uint256,uint16,uint16,uint16,uint256,bytes,uint256) external",
];
const vault = new ethers.Contract(quote.polygon_vault_contract_address, VAULT_ABI, signer);

const tx = await vault.createPosition(
  quote.position_seed_hex,
  quote.polymarket_market_id,
  BigInt(quote.polymarket_token_id),
  BigInt(quote.collateral_usdc_units),
  quote.leverage_bps,
  BigInt(quote.notional_usdc_units),
  quote.origination_fee_bps,
  quote.lifetime_fee_apr_bps,
  quote.liquidation_fee_bps,
  BigInt(quote.expected_open_trading_fee_usdc_units),
  quote.contract_signature,
  BigInt(quote.signature_expiry),
);
await tx.wait();
```

Code examples for Polymarket Safe, Proxy, and Deposit Wallet patterns: [On-Chain Integration](/for-developers/wallet-integration/on-chain-integration.md).
{% endtab %}

{% tab title="SDK (viem)" %}

```typescript
import { buildCreatePositionTx, buildApproveTx, verifyQuoteSignature } from "@dimes-dot-fi/sdk/contract";

// Verify the quote signature against on-chain contract info
await verifyQuoteSignature(client, result.quote, userAddress);

// Build approve + createPosition transactions (viem-compatible)
const approveTx = buildApproveTx(usdcAddress, vaultAddress, approvalAmount);
const createTx = buildCreatePositionTx(result.quote);

// Submit with viem's walletClient
await walletClient.writeContract(approveTx);
await walletClient.writeContract(createTx);
```

`buildCreatePositionTx` returns a viem-compatible object (`address`, `abi`, `functionName`, `args`) — pass it directly to `walletClient.writeContract()`.
{% endtab %}
{% endtabs %}

***

### 5. Monitor positions

{% tabs %}
{% tab title="REST API" %}

```bash
curl "https://api.dimes.fi/v1/prediction-markets/positions?status=open" \
  -H "Authorization: Bearer <jwt>"
```

Each position carries P\&L, mark price, margin health, liquidation price, and accrued fees. Display rules: [UI Guidelines](/for-developers/design-and-branding/ui-guidelines.md).
{% endtab %}

{% tab title="SDK" %}

```typescript
const positions = await client.getPositions({ status: "open" });

for (const position of positions) {
  console.log(position.marketTicker, position.current.unrealizedPnlUsd);
}
```

{% endtab %}

{% tab title="React" %}

```tsx
import { usePositions } from "@dimes-dot-fi/sdk/react";

function OpenPositions() {
  const { data: positions, isLoading } = usePositions({ status: "open" });

  if (isLoading) return <div>Loading...</div>;

  return (
    <ul>
      {positions?.map((p) => (
        <li key={p.id}>
          {p.marketTicker} — {p.current.unrealizedPnlUsd}
        </li>
      ))}
    </ul>
  );
}
```

{% endtab %}
{% endtabs %}

***

### 6. Close

The owner calls `vault.requestClose(position_key)`. Multiply sells tokens, distributes proceeds, emits `position.closed`. If the market resolves first, settlement is automatic.

{% tabs %}
{% tab title="ethers.js" %}

```javascript
const VAULT_ABI = ["function requestClose(bytes32) external"];
const vault = new ethers.Contract(vaultAddress, VAULT_ABI, signer);

const tx = await vault.requestClose(position.on_chain_position_key);
await tx.wait();
```

Code: [On-Chain Integration — Closing](/for-developers/wallet-integration/on-chain-integration.md#closing-a-position).
{% endtab %}

{% tab title="SDK (viem)" %}

```typescript
import { buildRequestCloseTx } from "@dimes-dot-fi/sdk/contract";

const closeTx = buildRequestCloseTx(vaultAddress, positionKey);
await walletClient.writeContract(closeTx);
```

{% endtab %}
{% endtabs %}

***

### What's next

* [SDK Installation](/for-developers/getting-started/sdk-installation.md) — setup, entry points, and peer dependencies
* [Sandbox](/for-developers/getting-started/sandbox.md) — how to get a sandbox key and test pUSD
* [Environments](/for-developers/getting-started/environments.md) — sandbox vs production
* [Contract Addresses](/for-developers/wallet-integration/contract-addresses.md) — verify what you're approving against
* [Authentication](/for-developers/api-and-events/authentication.md) — key management and rotation
* [On-Chain Integration](/for-developers/wallet-integration/on-chain-integration.md) — contract calls, wallet patterns, ABI
* [API Reference](/for-developers/api-and-events/api-reference.md) — full endpoint documentation
* [WebSocket Events](/for-developers/api-and-events/websocket.md) — real-time position state changes
* [Error Handling](/for-developers/api-and-events/error-handling.md) — error codes and retry logic
* [UI Guidelines](/for-developers/design-and-branding/ui-guidelines.md) — leverage sliders and position cards

Need help? Telegram link at [dimes.fi](https://dimes.fi).
