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

# PolymarketService

> Direct Polymarket CLOB calls outside the chat loop

`PolymarketService` is a direct HTTP client for the Polymarket CLOB endpoints exposed by the ILLA
gateway. Reach it through the `sdk.polymarket` getter when you want to place, cancel, read, redeem,
or withdraw imperatively — without going through the agent and the chat/tool loop.

The instance is created lazily on first access and reused for the lifetime of the SDK instance.

```ts theme={null}
import { IllaSDK } from '@illalabs/sdk'

const sdk = new IllaSDK({ apiKey: process.env.ILLA_API_KEY! })

const polymarket = sdk.polymarket // PolymarketService (lazy, cached)
```

You can pass a `polymarket` block to the `IllaSDK` constructor config to override the base URL,
timeout, headers, or route paths for this service.

## Authentication model

<Note>
  At the ILLA edge these routes pass the same gateway authentication as every other endpoint — an
  OAuth session bearer **or** an `x-api-key` (the SDK supplies the `apiKey` you configured). Inside
  the API there is no additional user-session binding for these routes; Polymarket-level
  authentication happens at the protocol level via a signed `authData` object passed in the request
  body — obtain it (and the order signature) beforehand by signing with
  `POST /api/v1/signatures/sign`.
</Note>

`authData` is `{ signature, timestamp, nonce, address }` (all strings); `getOrders` in particular
requires auth data signed immediately before the call.

## Methods

```ts theme={null}
// Each method POSTs to a Polymarket route on the ILLA gateway and resolves to a PolymarketResult.
postOrder(body: PolymarketPostOrderBody, options?):
  Promise<PolymarketResult<PolymarketPostOrderSuccessResponse>>      // /api/v1/polymarket/post-order
postRedeem(body: PolymarketPostRedeemBody, options?):
  Promise<PolymarketResult<PolymarketSafeExecuteSuccessResponse>>    // /api/v1/polymarket/post-redeem
postWithdraw(body: PolymarketPostWithdrawBody, options?):
  Promise<PolymarketResult<PolymarketSafeExecuteSuccessResponse>>    // /api/v1/polymarket/post-withdraw
getOrders(body: PolymarketGetOrdersBody, options?):
  Promise<PolymarketResult<PolymarketGetOrdersSuccessResponse>>      // /api/v1/polymarket/get-orders
cancelOrder(body: PolymarketCancelOrderBody, options?):
  Promise<PolymarketResult<PolymarketCancelOrderSuccessResponse>>    // /api/v1/polymarket/cancel-order
getRoutes(): PolymarketRoutes
```

`options` is `{ signal?: AbortSignal }`. `postRedeem` and `postWithdraw` submit signed Safe or
deposit-wallet operations to the Polymarket relayer; both resolve to a `PolymarketSafeExecuteSuccessResponse`.

## `PolymarketResult` envelope

Every method resolves to a discriminated result rather than throwing on request failure:

```ts theme={null}
type PolymarketResult<T> =
  | { isError: false; data: T }
  | { isError: true; error: PolymarketErrorResponse }
```

`PolymarketErrorResponse` is a union of a validation error
(`{ name: 'PolymarketInvalidParams', statusCode: 400, details.validationErrors[] }`) and an action
error (`{ success: false, error: string }`).

```ts theme={null}
const result = await sdk.polymarket.postOrder({
  order: signedOrder,
  signature: orderSignature,
  authData: { signature, timestamp, nonce, address },
  // optional: additionalSignatures, orderType ('GTC' | 'GTD' | 'FOK')
})

if (result.isError) {
  console.error(result.error) // PolymarketErrorResponse
} else {
  console.log('Order placed:', result.data.orderId, result.data.status)
}
```

## Routing by action

`routePolymarketAction` dispatches a single tagged request to the matching `PolymarketService`
method. `sdk.postPolymarketAction(request, options)` is the built-in facade shortcut that routes
against `sdk.polymarket`.

```ts theme={null}
routePolymarketAction(
  service: PolymarketService,
  request: PolymarketActionRequest,
  options?: PolymarketRequestOptions,
): Promise<PolymarketResult<PolymarketActionSuccessResponse>>
```

`PolymarketActionRequest` is a discriminated union on `action`:

| `action`                    | Method         |
| --------------------------- | -------------- |
| `polymarketPostOrder`       | `postOrder`    |
| `polymarketPostRedeem`      | `postRedeem`   |
| `polymarketPostWithdraw`    | `postWithdraw` |
| `polymarketPostGetOrders`   | `getOrders`    |
| `polymarketPostCancelOrder` | `cancelOrder`  |

The `polymarketAuth` action is intentionally excluded — it is handled client-side and has no
server endpoint.

```ts theme={null}
import { IllaSDK, routePolymarketAction } from '@illalabs/sdk'
import type { PolymarketActionRequest } from '@illalabs/sdk'

const sdk = new IllaSDK({ apiKey: process.env.ILLA_API_KEY! })

const request: PolymarketActionRequest = {
  action: 'polymarketPostCancelOrder',
  body: { authData, orderId: '0xorder...' },
}

// Facade shortcut:
const result = await sdk.postPolymarketAction(request)

// ...or route against any PolymarketService instance directly:
// const result = await routePolymarketAction(sdk.polymarket, request)

if (result.isError) {
  console.error(result.error)
} else {
  console.log('Success:', result.data) // PolymarketActionSuccessResponse
}
```

## `PolymarketService` vs the tool-execution path

Every Polymarket order reaches the CLOB the same way — a `POST` to the Polymarket routes this
service wraps. What differs between the two paths is who *builds* the order, not how it is
submitted:

* **Agent-assisted build.** You send a natural-language message; the model emits a
  `predictionMarketsBet` tool call that arrives in `pendingTools` with the signature requests for
  the order. Your executor signs and reports back with `sendToolResults` — but the LLM is not in
  the loop for submission: your app still posts the signed order to
  `/api/v1/polymarket/post-order` (i.e. `sdk.polymarket.postOrder(...)`) itself. See
  [Handling Tool Execution](/sdk/guides/handling-tool-execution).
* **Fully imperative.** Your app builds and signs the order and `authData` without involving the
  agent, then calls `sdk.polymarket.postOrder(...)` (or routes by action) directly.

Either way `PolymarketService` is the submission surface; the agent path just derives a built,
ready-to-sign order from natural language first.

## Related pages

* [ILLA SDK](/sdk/api/illa-sdk)
* [Submitting Hyperliquid actions](/sdk/api/hyperliquid-submit)
* [Handling Tool Execution](/sdk/guides/handling-tool-execution)
* [Error handling](/sdk/concepts/error-handling)
