> For the complete documentation index, see [llms.txt](https://docs.gensyn.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gensyn.ai/tech/delphi-sdk/api.md).

# API Reference

## Overview

All REST API methods read data from the Delphi API and require `DELPHI_API_ACCESS_KEY` to be set (except `health()`).

### health()

Check service availability. Does not require authentication.

```typescript
const { status } = await client.health();
```

### Markets

#### listMarkets(*params*)

Retrieve markets with optional filtering and pagination using `listMarkets`.

```typescript
const { markets } = await client.listMarkets({
  status: "open",
  category: "crypto",
  orderBy: "liquidity",    // "liquidity" | "created" | "settles_at"
  verifiable: true,
  skip: 0,
  limit: 50,
});
```

#### **Parameters**

| Field                           | Type           | Default            | Description                                                                     |
| ------------------------------- | -------------- | ------------------ | ------------------------------------------------------------------------------- |
| `skip`                          | `number`       | `0`                | Pagination offset                                                               |
| `limit`                         | `number`       | `50`               | Maximum records returned                                                        |
| `status`                        | `MarketStatus` | —                  | `"open"` \| `"awaiting_settlement"` \| `"settled"` \| `"expired"` \| `"failed"` |
| `category`                      | `string`       | —                  | Filter by metadata category                                                     |
| `orderBy`                       | `string`       | `liquidity`        | `liquidity`, `created`, or `settles_at`                                         |
| `competitionId`                 | `string`       | Active competition | Competition to query                                                            |
| `verifiable`                    | `boolean`      | —                  | Filter by verifiable settlement                                                 |
| `pricesAndImpliedProbabilities` | `boolean`      | —                  | Include prices and implied probabilities                                        |

#### getMarket(*params*)

Retrieve a single market by ID.

```typescript
const market = await client.getMarket({
  id: "0xMarketContractAddress",
  competitionId: "optional-competition-id",
});
```

{% hint style="info" %}
This returns the same `Market` type. The `id` comes from `listMarkets`.
{% endhint %}

#### Market Type

```typescript
export interface Market {
  id: string; // On-chain contract address of the market proxy
  appMarketId: string; // UUID identifying the market in the Delphi app UI
  marketUrl: string; // Direct link to the market on the Delphi app
  status: MarketStatus; // "open" | "awaiting_settlement" | "settled" | "expired" | "failed"
  category: string; // Market category, e.g. "crypto", "sports", "politics"
  deployer: string; // Wallet address that deployed/created the market
  implementation: string; // Market implementation contract address
  metadataUri: string; // URI pointing to the market metadata
  metadataUriContentHash: string; // Content hash for the metadata URI
  metadata: unknown; // Parsed market metadata returned by the API
  dataSources: unknown; // Data sources used for market resolution/verification
  createdAt: string; // ISO timestamp when the market was created
  fetchedAt: string | null; // ISO timestamp when metadata was last fetched, or null
  fetchResponseStatus: string | null; // Status from the metadata fetch attempt, or null
  resolvesAt: string | null; // ISO timestamp when the market is expected to resolve, or null
  settledAt: string | null; // ISO timestamp when the market was settled, or null
  settlesAt: string | null; // ISO timestamp for scheduled settlement, or null
  winningOutcomeIdx: string | null; // Winning outcome index after settlement, or null
  tradingFee: string | null; // Trading fee value returned by the API, or null
  proof: string | null; // Resolution proof or verification reference, or null
  error: string | null; // Error message related to market metadata/resolution, or null
  verifiable: boolean; // Whether the market has verifiable settlement enabled
}
```

#### Metadata Shape

```typescript
const meta = market.metadata as {
  question?: string;            // The market question
  title?: string;               // Alternative title
  description?: string;
  category?: string;
  outcomes?: string[];          // Outcome labels — index matches outcomeIdx
  resolutionCriteria?: string;
  endDate?: string;             // ISO date
} | null;
```

{% hint style="danger" %}
The `outcomes` array is critical for labelling: `outcomes[0]` is the label for `outcomeIdx: 0`.
{% endhint %}

The key address fields here are:

| Field                   | Purpose                                                           |
| ----------------------- | ----------------------------------------------------------------- |
| `market.id`             | Pass to `getMarket({ id })`                                       |
| `market.id`             | Pass as `marketAddress` to SDK trading, quote, and approval calls |
| `market.implementation` | Implementation contract address; do not use as `marketAddress`    |

### Market Status Values

```typescript
type MarketStatus =
  | "open"
  | "awaiting_settlement"
  | "settled"
  | "expired"
  | "failed";
```

| Status                | Meaning                                                  |
| --------------------- | -------------------------------------------------------- |
| `open`                | Trading active                                           |
| `awaiting_settlement` | Trading deadline passed, awaiting settlement             |
| `settled`             | Winning outcome set; positions redeemable                |
| `expired`             | Market expired without settlement; liquidate positions   |
| `failed`              | Oracle could not resolve the market; liquidate positions |

{% hint style="info" %}
The API returns these as *strings*.

The underlying contract exposes an `int enum`: 0 = open, 1 = awaiting settlement, 2 = settled, 3 = expired, and 4 = failed.
{% endhint %}

A winning outcome is set by the oracle on automated-settlement markets. Legacy markets use the creator's winner submission.

### Usage Patterns

You can paginate through all markets like this:

```typescript
let skip = 0;
const limit = 50;
const all: Market[] = [];

while (true) {
  const { markets } = await client.listMarkets({ status: "open", skip, limit });
  if (!markets || markets.length === 0) break;
  all.push(...markets);
  if (markets.length < limit) break;
  skip += limit;
}
```

Or, find a market using a question keyword:

```typescript
const { markets } = await client.listMarkets({ status: "open", limit: 100 });
const match = markets?.find(m => {
  const meta = m.metadata as { question?: string } | null;
  return meta?.question?.toLowerCase().includes("keyword");
});
```

### Positions

#### listPositions(*params*)

Retrieve positions for a wallet address.

```typescript
const { positions } = await client.listPositions({
  wallet: "0xYourWalletAddress",
  redeemedOrLiquidated: false,
  skip: 0,
  limit: 50,
});
```

#### Position Type

```typescript
interface Position {
  id: string;
  marketProxy: string;      // Market proxy address (use as marketAddress)
  wallet: string;
  outcomeIdx: string;       // Outcome index as string — parse with parseInt()
  shares: string;           // 18-decimal bigint as string — parse with BigInt()
  redeemedOrLiquidated: boolean;
  tokensRedeemed: string;   // Collateral amount as a 6-decimal bigint string
  marketStatus: "open" | "awaiting_settlement" | "settled" | "expired" | "failed";
}
```

Be careful when parsing, because `shares` and `tokensRedeemed` are *string representations* of [bigints](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html#bigint).

```typescript
const shares = Number(BigInt(position.shares)) / 1e18;
const tokensRedeemed = Number(BigInt(position.tokensRedeemed)) / 1e6;
const outcomeIdx = parseInt(position.outcomeIdx);
```

### Redemption

Markets must be `settled` (winner submitted) before redeeming. Only holders of the winning outcome receive tokens.

{% hint style="warning" %}
`expired` and `failed` markets have no winning outcome. Use `liquidate()` rather than `redeemMarket()` for these positions.
{% endhint %}

{% hint style="warning" %}
Positions with `shares === "0"` cannot be redeemed or liquidated because the wallet holds no stake.

The positions API may return zero-share entries for markets the wallet previously participated in but fully exited. Always check `BigInt(position.shares) > 0n` before attempting redeem or liquidate calls.
{% endhint %}

#### 1. Single (Market) Redemption

```typescript
const { transactionHash, sharesIn, tokensOut } = await client.redeemMarket({
  marketAddress: "0x..." as `0x${string}`,
});
console.log(`Redeemed ${Number(sharesIn) / 1e18} shares → ${Number(tokensOut) / 1e6} collateral tokens`);
```

#### 2. Batch (Market) Redemption

```typescript
const { results, totalTokensOut } = await client.redeemPositions({
  marketAddresses: ["0x...", "0x..."],
});

for (const r of results) {
  if (r.success) {
    console.log(`${r.marketAddress}: ${Number(r.tokensOut!) / 1e6} collateral tokens`);
  } else {
    console.error(`${r.marketAddress}: ${r.error}`);
  }
}
console.log(`Total redeemed: ${Number(totalTokensOut) / 1e6} collateral tokens
`);
```

#### 3. Batch-Redeeming all Unredeemed, Settled Positions

```typescript
const { positions } = await client.listPositions({
  wallet: myAddress,
  redeemedOrLiquidated: false,
});

const settledProxies: `0x${string}`[] = [];
for (const p of positions ?? []) {
  if (BigInt(p.shares) === 0n) continue;
  const market = await client.getMarket({ id: p.marketProxy });
  if (market.status === "settled") {
    settledProxies.push(p.marketProxy as `0x${string}`);
  }
}

if (settledProxies.length > 0) {
  const { results, totalTokensOut } = await client.redeemPositions({
    marketAddresses: settledProxies,
  });
}
```

#### 4. Liquidating Expired or Failed Positions

`getMarketStatus()` reads the current on-chain status. Use it when REST data may be stale.

```typescript
import { LIQUIDATABLE_MARKET_STATUSES } from "@gensyn-ai/gensyn-delphi-sdk";

for (const p of positions ?? []) {
  if (BigInt(p.shares) === 0n) continue;

  const marketAddress = p.marketProxy as `0x${string}`;
  const status = await client.getMarketStatus(marketAddress);
  if (!LIQUIDATABLE_MARKET_STATUSES.includes(status)) continue;

  await client.liquidate({
    marketAddress,
    outcomeIndices: [0, 1], // Binary market; include every outcome index.
  });
}
```

#### Estimating Portfolio Value

Estimate the current liquidation value of all active positions:

```typescript
const { positions } = await client.listPositions({
  wallet: myAddress,
  redeemedOrLiquidated: false,
});

let totalValue = 0;
for (const p of positions ?? []) {
  const shares = BigInt(p.shares);
  if (shares === 0n) continue;

  const marketAddress = p.marketProxy as `0x${string}`;
  const outcomeIdx = parseInt(p.outcomeIdx);

  try {
    const { tokensOut } = await client.quoteSell({
      marketAddress, outcomeIdx, sharesIn: shares,
    });
    totalValue += Number(tokensOut) / 1e6;
  } catch {
    console.log(`${marketAddress} outcome ${outcomeIdx}: cannot quote (market may be closed)`);
  }
}
console.log(`Total estimated value: ${totalValue.toFixed(4)} collateral tokens`);
```
