@probleeprotocol/sdk
v1.0.4
Published
TypeScript SDK for the Problee Agent API. Discover markets, get quotes, prepare trades, subscribe to events.
Maintainers
Readme
@probleeprotocol/sdk
TypeScript SDK for the Problee Agent API.
Problee Money (PM) is play money: it has no cash value and cannot be redeemed, withdrawn, or sent to another user.
AI coding agents should read AGENTS.md; it is generated from package metadata and OpenAPI artifacts.
Registry status:
@probleeprotocol/sdkreleases with the lockstep SDK surface. Install the package or integrate directly against https://api.problee.com/api/agent/v1/openapi.json.The current package uses generated OpenAPI 3.1 types with hand-authored ergonomic wrappers. v1.0.0 will move more of the client surface to generated code while preserving the small wrapper API.
Install
npm install @probleeprotocol/sdk
# or
pnpm add @probleeprotocol/sdkZero runtime dependencies. Node 18+ (uses native fetch).
Get an API key
https://problee.com/developer/register-agent
Or use the @probleeprotocol/mcp CLI:
npx @probleeprotocol/mcp registerUsage
import { ProbleeClient } from '@probleeprotocol/sdk';
const client = new ProbleeClient({ apiKey: process.env.PROBLEE_API_KEY! });
// Read addresses from discovery on every run. Never copy a token or contract
// address into an agent configuration. If this call answers for a chain, those
// addresses are the live ones — there is nothing further to verify.
const { chains } = await client.api.discovery.getDiscoverContracts({ query: { chainId: 8453 } });
const [base] = chains;
if (!base) throw new Error('Chain 8453 is not live');
console.log(base.collaterals, base.factories, base.approvals);
// Who am I?
const me = await client.me();
console.log(me.tier, me.scopes);
// Discover open markets
const { markets } = await client.markets.list({ marketState: 'open', pageSize: 10 });
console.log(markets[0].marketState);
// `marketState` is the exact canonical lifecycle. There is no coarse lifecycle alias.
// Dispute actions expose `challengerBondWei`/`disputeBondWei` as the market's
// open PM creation bond, not a global base bond.
// Approvals, if this chain's collateral has any. A collateral whose
// `settlement` is `committed` — play money, today — is allowance-free: its
// fills are entries on the venue commit ledger and move no token balance, so
// this list comes back empty and there is nothing to broadcast.
//
// For a collateral that settles on chain there are at most two, per collateral,
// valid forever (the MarketRouter is a permanent UUPS proxy, so one approval
// covers every market and every upgrade):
// BUY (AMM + orderbook): approve(collateral ERC-20 -> router, MAX)
// SELL (LMSR + orderbook): setApprovalForAll(OutcomeToken1155 -> router, true)
// Cancel and claim/redeem need no approval. The router address is permanent;
// never approve a per-market clone — route all order-book liquidity through
// Router.fillOrderbook.
const { approvals } = await client.trade.approvals({ chainId: 8453 });
for (const approval of approvals) {
// approval = { kind, reason, chainId, token, spender (the stable router), amount? }
// Broadcast each once with your own wallet client; ensureApprovals({ readAllowance })
// filters out any you have already granted.
console.log(approval.kind, '→', approval.spender);
}
// Get a quote
const quote = await client.trade.quote({
marketAddress: '0x...',
side: 0,
type: 'buy',
amount: '100000000000000000000',
chainId: 8453,
});
console.log(quote.outcomeTokensOut, quote.priceImpact, quote.quotedAt);
// Prepare a trade (returns an EIP-712 intent to sign)
const prepared = await client.trade.prepare({
marketAddress: '0x...',
side: 0,
tradeType: 'buy',
amount: '100000000000000000000',
chainId: 8453,
slippageBps: 100,
});
// Sign it and hand it back. The protocol submits the trade and pays the gas, so
// there is nothing for you to broadcast and no receipt to poll. `executeIntent`
// signs `prepared.signPayload.typedData` exactly as returned and keys the
// request on `prepared.signPayload.digest` — the digest the router burns once,
// which makes a retry the same trade by the protocol's own rule.
const accepted = await client.trade.executeIntent(prepared, {
signTypedData: (typedData) => account.signTypedData(typedData),
});
// Sizing is exact-input, and the unit of `amount` depends on the side:
// BUY → `amount` is the COLLATERAL you spend (e.g. 1 PM = "1000000").
// SELL → `amount` is the number of OUTCOME TOKENS you sell — the same unit as
// `positions[].outcome1Shares`, NOT collateral.
// To close or trim a position you do NOT need to fetch a balance or reconcile
// rounding. Three sell sizings (use exactly one), all sized server-side from your
// live balance — work on `trade.prepare` and `trade.simulate`:
// amount → exact outcome tokens to sell (the unit above)
// closePercent (1–100)→ sell this % of your position; 100 = full close
// targetCollateralOut → "sell ~N collateral worth" (mirror of buying N worth)
const closed = await client.trade.prepare({
marketAddress: '0x...',
side: 1,
tradeType: 'sell',
closePercent: 100, // 100 = full close; e.g. 50 = sell half
chainId: 8453,
});
const cashOut = await client.trade.prepare({
marketAddress: '0x...',
side: 1,
tradeType: 'sell',
targetCollateralOut: '1000000', // ≈ 1 PM out; capped at your balance
chainId: 8453,
});
// On an over-sell with an explicit `amount`, the 409 response carries `available`
// and `requested` in the same outcome-token denomination as the market collateral
// (PM: 6 decimals), so you can re-size in a single follow-up call.
// A sell on a market that settles ON CHAIN requires the one-time
// setApprovalForAll(OutcomeToken1155 -> router) above, and its terminal call is
// Router.sellBinary/sellTernary for LMSR or Router.fillOrderbook for order-book
// execution. A sell on a `committed` market requires no approval and has no
// terminal call: it is paid at match against the venue ledger.
// Preflight and propose a source-owned market
// market-creation-example:start
const { chains: creationChains } = await client.api.discovery.getDiscoverContracts({
query: { chainId: 8453 },
});
const creationChain = creationChains[0];
if (!creationChain) throw new Error('Chain 8453 is not live');
const creationCollateral =
creationChain.collaterals.find(
(collateral) => collateral.role === 'protocol' && collateral.capabilities.creation
) ?? creationChain.collaterals.find((collateral) => collateral.capabilities.creation);
if (!creationCollateral) {
throw new Error('Chain 8453 has no creation-capable collateral');
}
const terms = {
question: 'Will BTC close above $100,000 on Coinbase on December 31, 2026?',
category: 'CRYPTO' as const,
outcomes: [
{ index: 1 as const, label: 'Outcome 1' },
{ index: 2 as const, label: 'Outcome 2' },
],
closeTime: '2026-12-31T23:59:00.000Z',
chainId: creationChain.chainId,
collateralToken: creationCollateral.token,
externalId: 'crypto:btc:100k:2026-12-31',
resolutionCriteria: 'Resolve from the public Coinbase BTC-USD daily close on December 31, 2026.',
resolutionSource: {
type: 'crypto_price_v1',
venue: 'Coinbase BTC-USD',
},
};
const preflight = await client.negotiation.preflight({ terms });
if (preflight.ok) {
const proposed = await client.negotiation.propose(
{ terms },
{ idempotencyKey: 'crypto:btc:100k:2026-12-31:propose' }
);
console.log(proposed.state);
}
// market-creation-example:end
// Publish beginner-friendly market surface data
await client.markets.publishNote('0x...', {
chainId: 8453,
text: 'Liquidity is concentrated near 58%.',
});
await client.markets.publishPriceChart('0x...', {
chainId: 8453,
symbol: 'BTC',
source: 'Binance',
sourceTimestamp: Date.now(),
latest: { timestamp: Date.now(), value: 103240.12 },
unit: 'USD',
});
await client.markets.publishScoreboard('0x...', {
chainId: 8453,
homeTeam: 'LAL',
awayTeam: 'BOS',
homeScore: 82,
awayScore: 79,
period: 'Q4',
clock: '07:42',
status: 'live',
});
// Check creator funds after resolution
const funds = await client.trade.creatorFunds();
for (const market of funds.creatorFunds.markets) {
// Rows with `action` say what is collectable. To collect, POST
// /trade/creator-funds/collect: the protocol submits those market-local calls
// and pays the gas, so there is nothing here for you to sign or broadcast.
console.log(market);
}Creation model selection:
- Auto-priced market is the default. Omit
pricingModel; use seed liquidity and optional opening probabilities. - Order book market is explicit. Set
pricingModel: "ORDERBOOK"for binary markets with trader-set prices, live order book depth, limit orders, and router-filled market buys/sells.
Coverage in v0.x
| Method | Endpoint |
| ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| client.me() | GET /me |
| client.markets.list(params?) | GET /discover/markets |
| client.markets.get(address, params?) | GET /discover/markets/{address} |
| client.markets.exists(externalId) | GET /discover/markets/exists |
| client.markets.chart(address, params?) | GET /discover/markets/{address}/chart |
| client.markets.publishNote(address, body) | POST /markets/{address}/surface |
| client.markets.publishPriceChart(address, body) | POST /markets/{address}/surface |
| client.markets.publishScoreboard(address, body) | POST /markets/{address}/surface |
| client.markets.publishSurface(address, body) | low-level semantic wrapper |
| client.markets.registerCreated(address, body, opts) | POST /markets/{address}/register |
| client.negotiation.preflight(body) | POST /negotiate/preflight |
| client.negotiation.propose(body, opts) | POST /negotiate/propose |
| client.negotiation.list(params?) | GET /negotiate |
| client.negotiation.get(id) | GET /negotiate/{id} |
| client.negotiation.accept(id, opts) | POST /negotiate/{id}/accept |
| client.negotiation.reject(id, body, opts) | POST /negotiate/{id}/reject |
| client.negotiation.checkpoint(id, body, opts?) | PUT /negotiate/{id}/client-checkpoint |
| client.negotiation.prepareDeploy(id, opts) | POST /negotiate/{id}/prepare-deploy |
| client.negotiation.commitDeploy(id, body, opts) | POST /negotiate/{id}/commit-deploy |
| client.creatorInventory.scopes() | GET /me/market-inventory/scopes |
| client.creatorInventory.page(params) | GET /me/market-inventory |
| client.trade.quote(body) | POST /trade/quote |
| client.trade.prepare(body) | POST /trade/prepare |
| client.trade.executeIntent(prepared, opts) | ergonomic helper — signs the prepared intent, posts POST /trade/execute-intent keyed on its digest |
| client.trade.creatorFunds(params?) | GET /trade/creator-funds |
| client.trade.status(txHash, { chainId }) | GET /trade/status/{txHash} |
| client.trade.fills(params) | GET /trade/fills |
| client.trade.approvals(params?) | GET /discover/contracts |
| client.trade.ensureApprovals(params?) | ergonomic helper — filters already-granted approvals |
| client.events.types() | GET /events/types |
| client.events.discovery() | GET /events/discovery |
| client.events.subscribe(types, opts?) | POST /events/subscribe |
| client.events.unsubscribe(types, opts?) | POST /events/unsubscribe |
| client.request<T>(method, path, body?) | escape hatch — typed fetch over any endpoint |
For everything else, use client.request() until v1.0.0 lands. The escape hatch returns whatever the server sends, validated as JSON.
Orderbook markets use the generated Agent REST surface under client.orderbook
(or createOrderbookClient() for a dedicated wrapper). Methods mirror
POST /orderbook/*: get, batchGet, openOrders, events, placeOrder,
batchPlaceOrders,
cancelOrder, confirmCancel, cancelAll, sweepEstimate,
and signAndPlace. Cancellation on a market that settles on chain is
prepare → wallet broadcast → confirm; cancelOrder and cancelAll return
prepared calldata, never premature terminal success. confirmCancel returns either an active-risk
OPEN|PARTIALLY_FILLED plus MINED/PENDING_FINALITY, or (only when the same
canonical transaction and settlement log are already persisted) CANCELLED
plus MINED/FINALIZED. Reconcile finalized cancelled lifecycle replay as the
durable terminal authority.
Limit prices are integer bps on the market's banded grid, or a 0–1
priceDecimal. Build the ladder from tradingRules.priceBands on
client.markets.get(address) — an ascending, disjoint
{ minBps, maxBps, tickBps }[] — never from an assumed tick. Default-tick
markets are 10–490 by 10, 500–9500 by 100, and 9510–9990 by 10: 189 rungs, a
tenth of a cent in the tails. A 1.2c bid is 120 and is legal; 125 is not,
and the PRICE_OFF_TICK refusal names 120 and 130 in
nearestBelowBps/nearestAboveBps. tradingRules.priceIncrementBps is still
the base tick (100 by default) and multiples of it stay legal, so a coarse
integration keeps working. Sizes must clear
max(minRestingShares, ceil(minRestingNotional * 10000 / price)) — 50 shares
and the venue's flat trading minimum on PM markets — or AMOUNT_BELOW_MINIMUM
returns that effective bound as minOrderShares. That venue minimum is flat and
price-independent, and it is also the whole taker floor — the book snapshot
publishes it per outcome as effectiveMinBuyAmount. A market's own
tradingRules.minBuyAmount is deprecated and unenforced: settlement asserted
it per settlement leg until the 2026-08-31 beacon upgrade removed the assertion
from every live market at once, and it now records only what the market was
stamped with. Do not size against it. Read GET /discover/fees for default taker
rates.
For orderbook:l2:v2 bootstrap, request the exact chain with public, unsided
depth 50. A checksummed REST revision 0 is a valid upgrade baseline and may
already be nonempty; realtime v2 frames begin at revision 1.
Use client.orderbook.batchGet({ requests }) for one to 100 unique exact-chain
destination books with view: "executable_for_caller". The API-key wallet is
excluded server-side; the all-or-nothing response preserves request order and
binds every chain/address to a complete non-null L2 cursor. Never send a wallet
field or treat public aggregate depth as caller-executable liquidity.
REST client.orderbook.openOrders() and MCP problee_get_open_orders both
derive the wallet from the authenticated session, accept no caller-selected
wallet, and require reservedAmount plus nullable reservationExpiresAt on
every own-order row. Treat the persisted reserved amount as unavailable until a
later page publishes a lower value; nominal timestamp passage is not a release.
Page own orders with limit/cursor; every page carries mandatory
nextCursor/hasMore, and callers must continue until both indicate the
terminal boundary. Each own-order row always carries clOrdId: a string when
supplied at placement or clOrdId: null for a legacy/order-without-id row.
Do not synthesize an identifier for null. Placement and cancellation accept
client order ids up to 200 characters. Replay the durable private lifecycle
journal with client.orderbook.events({ afterSequence }). Realtime reports are
acceleration; advance the stored cursor only after applying the REST event.
signAndPlace runs the full limit-order flow: unsigned place, sign the
server-returned EIP-712 typedData exactly as returned (never derive the domain
or types locally — the server payload is authoritative), and resubmit under a
derived <key>:signed idempotency key. Inject any signer:
import { privateKeyToAccount } from 'viem/accounts';
const account = privateKeyToAccount(process.env.WALLET_KEY as `0x${string}`);
const placed = await client.orderbook.signAndPlace(
// 50 outcome tokens on a PM market (6-decimal raw denomination).
{ marketAddress, side: 0, priceDecimal: 0.55, amount: '50000000', clOrdId: 'mm-1' },
{
idempotencyKey: 'place-mm-1',
signTypedData: (typedData) => account.signTypedData(typedData as never),
}
);requiresSignature on the raw placeOrder response still exposes the manual
two-step for custom flows. There is no signAndPlaceBatch:
batchPlaceOrders has no signing-payload branch (every order must arrive
pre-signed), so loop signAndPlace, or pre-sign and batch.
Market surface helpers publish by intent. note uses creator content
retention; price_chart, scoreboard, and ticker use bounded live state
with TTL, source metadata, coalescing, and stale update rejection.
Surface publishes draw on a dedicated per-agent data budget, separate from the
trade/write budget — high-cadence enrichment never competes with trades,
settlements, or resolution. Per-market fairness is governed independently (one
update per second per market is well within the quota). Read the live
rateLimits and dataPlane fields from client.me() to inspect headroom.
Creator funds separate market balance from creation bond. Treat the returned balance, bond status, and actions as the public contract; do not infer internal resolution accounting from local formulas.
Settlement lanes
Every market names the engine that settles it in a settlement field, and the
two behave differently enough that it is the first thing to branch on.
committed is the venue commit ledger, and it is where play money trades.
A fill is paid the moment it matches, against balances the venue holds, and
those fills are recorded on Base in batches — one CommitLedger.commitBatch
transaction carrying many fills as standard ERC-1155 events under a chained
root, so every balance is recomputable from Base alone. There are no approvals,
no per-trade transaction, no market contract (the address is a real CREATE2
address nobody deploys to), and no claim: winnings are credited to the holder at
resolution, so a claim call reports a committed market SKIPPED rather than
ever becoming eligible.
onchain keeps collateral and positions in the wallet. Every fill is its
own Base transaction, the approvals below apply, and a claim is a real
market-local call.
On both lanes client.trade.prepare() returns a signable EIP-712 intent, never
a transaction: hand the whole prepared trade to client.trade.executeIntent()
with a signTypedData callback. The protocol submits and pays the gas.
Trading approvals
These apply to a collateral that settles ON CHAIN. A committed collateral is
allowance-free and client.trade.approvals() returns nothing for it.
Automated trading needs at most two one-time approvals per such collateral, and
they stay valid forever — each per-collateral MarketRouter is a permanent UUPS
proxy, so a single approval survives every future market and every contract
upgrade.
- Buy (AMM + order book):
approve(collateral ERC-20 → router, MAX). - Sell (LMSR + order book):
setApprovalForAll(OutcomeToken1155 → router, true). - Cancel and claim/redeem need no approval.
client.trade.approvals({ chainId, collateral? }) returns the exact recipes
(kind, reason, token, spender, amount?) plus the same per-chain
contract catalog returned by GET /discover/contracts. Human identity is a
separate global service and is not exposed as chain-local trading periphery.
The spender is always the stable router, never a per-market clone.
client.trade.ensureApprovals({ owner, readAllowance }) filters out approvals
you have already granted. Never approve/setApprovalForAll a per-market clone
— route all order-book liquidity through the router's fillOrderbook and
signed-order entrypoints.
Agent market creation
Agents bring their own sources and strategies. Problee supplies the contract: verified-human ownership, scoped API keys, wallet-bound market creation, reputation, trading, settlement, and distribution.
Use required top-level resolutionCriteria for the human-readable settlement
contract. Use resolutionSource as an opaque envelope owned by your agent; the
protocol requires only type and stores additional source metadata verbatim.
Creation is a checkpointed economic flow, and it ends in one of two lanes.
client.negotiation.propose()andclient.negotiation.accept().client.negotiation.checkpoint()stores the immutable, private resume capsule. This must succeed before deployment can be prepared; identical replay is intrinsically safe and a conflicting replay returns409.
Then the RELAYED lane — the one a committed market uses, and the one a wallet holding no gas needs. It has no wrapper on this client yet; call the two routes directly:
POST /negotiate/{id}/prepare-relayed-deployreturns an EIP-712 creation authorization binding the negotiated terms.- Sign it with the creator wallet and post it to
POST /negotiate/{id}/relay-deploy. The protocol records the creation and pays any gas — it broadcastscreateMarketForon an on-chain collateral, and on a committed one there is nothing to broadcast, so the market is written at the address that authorization already names. The market is registered as it is recorded: no tx hash to commit, no metadata call to follow.
Or the WALLET lane, which needs a funded wallet and produces an on-chain market:
client.negotiation.prepareDeploy()returns one versionedcreationIntentplus a fullPREPAREDhostedAdmissionreceipt. Treat the nested intent as the only calldata/economics authority: require the supported version, decode and re-encode the declared factory ABI, recompute the content, calldata, economics, and receipt hashes, and verify the receipt signature against the release authority pinned independently from this response.- Approve the exact token-addressed amounts in
creationIntent.economics, then broadcastcreationIntent.calldatatocreationIntent.economics.factoryAddressfromcreationIntent.creatorAddress. Never reconstruct these values from flat response echoes. client.negotiation.commitDeploy()records the tx hash and reconciles that on-chaincreatedBymatches the boundExternalAgent.walletAddress, thenclient.markets.registerCreated()attaches the metadata.
On startup, use client.creatorInventory.scopes() and cursor through
client.creatorInventory.page() for every returned release/chain. This is the
durable recovery path for a deployment that reached Protocol but was not
recorded locally before a crash.
See the Agent Creator Kit at https://problee.com/developer for a source-agnostic dry-run loop, local quality linter, and adapter stubs.
Identity linking
Multi-wallet identity linking (link-code, link-consent, pending-links,
approve-links, unlink) has no ergonomic wrapper yet — call it on the
generated client through client.api.identity.* (method names mirror the
OpenAPI operationIds, for example postIdentityLinkConsent).
Resolution: Invalid / Void
Markets can settle Invalid / Void ("neutral void") instead of picking a
winner: there is no winning outcome and every share redeems an equal 1/N split of the
collateral. It is not a refund of each trader's purchase price. Void is
reserved outcome index 0 everywhere in the resolution surface, and only
markets whose supportsVoid is true accept it.
Four things to get right, because 0 is falsy:
- Proposing. A creator resolves void with
outcomeIndex: 0onPOST /resolve/propose/prepare; the signedCreatorIntentcarriesisVoid: true. - Disputing. A void proposal is challengeable like any other. On
GET /discover/markets/{address}/resolution-statethedisputeActionhasproposedOutcome: 0, andcounterOutcomeOptionslists every numbered outcome (void excludes nothing). YourcounterOutcomeis always 1-3 — you rebut "no valid answer" by asserting a real one. - Voting. Ballots are
0 | 1 | 2 | 3.0is a first-class neutral-void ballot: tallied with the rest, able to become the unique Human Vote guidance and silence default, and reward-eligible. A session reviewing a void proposal reportssubmittedOutcome.outcomeIndex: 0. - Claiming. A voided market ends at
marketState: "void"withresolutionStage: "CANCELLED"andfinalOutcome: null— but claims are open. Branch onmarketState, never on a non-nullfinalOutcome.
const state = await client.api.discovery.getDiscoverMarketsByAddressResolutionState({
params: { path: { address: marketAddress } },
});
if (state.disputeAction?.proposedOutcome === 0) {
// Creator proposed Invalid / Void — counter with any numbered outcome.
const options = state.disputeAction.preparation.options.counterOutcomeOptions;
}
// Terminal void still pays out.
const claimable = state.marketState === 'void' || state.finalOutcome !== null;The market.resolved and market.challengeWindowOpened events carry
isVoid: true alongside outcome: 0 for the same reason — never read a
falsy outcome as "unresolved".
Live events
const discovery = await client.events.discovery();
console.log(discovery.webSocket.url);
await client.events.subscribe(['market.created'], {
idempotencyKey: 'events-subscribe-market-created',
});
const connection = await client.events.connect({
types: ['market.created', 'market.resolved'],
webSocketFactory: (url, { headers }) => new WebSocket(url, { headers }),
onEvent: (event) => {
console.log(event.type, event._seq);
},
});/events/subscribe is a REST control-plane write for live WebSocket
subscriptions, not an SSE stream. client.events.connect() reads
/events/discovery, authenticates with the API-key header, subscribes on open,
tracks _seq as lastEventId, and reconnects with the latest sequence. Pass a
server-side WebSocket factory such as ws; browser WebSockets cannot set the
required Authorization header. Use webhooks as the async fallback when a long
running WS connection is not available.
Private order lifecycle events are not subscribed events — they arrive on the
wallet-scoped execution.report frame, auto-delivered to the authenticated
wallet on the same onEvent callback (typed AgentExecutionReportEvent). It
carries order identity, finality, stable event ID, and durable wallet sequence;
realtime delivery is at-most-once, so replay gaps via
client.orderbook.events({ afterSequence }). See
/events/discovery → walletScopedChannels.
Market data
Use the public market-data WebSocket for prices, trades, and orderbook updates:
const marketData = await client.api.marketData.getMarketDataDiscovery();
console.log(marketData.webSocket.url); // wss://api.problee.com/api/consumer/market/wsSubscribe with chainId, up to 100 markets, and channels
market:update, trade:new, orderbook:update, and orderbook:l2 (full
50-level depth with a per-market monotonic seq). Keep REST quote/orderbook
reads as execution authority; Agent WS is only the lifecycle and negotiation
control plane.
Errors
All non-2xx responses throw ProbleeError:
import { ProbleeClient, ProbleeError } from "@probleeprotocol/sdk";
try {
await client.trade.quote(...);
} catch (err) {
if (err instanceof ProbleeError) {
console.error(err.status, err.code, err.requestId);
console.error(err.body); // full RFC 7807 problem+json body
}
}Required scopes per endpoint
| Capability | Required API-key scope |
| --------------------------------------- | ---------------------- |
| List chains, read public metadata | none |
| Read markets and events | markets:read |
| Quote trades | trade:quote |
| Create markets | markets:create |
| Prepare or execute trades | trade:execute |
| Read portfolio, fees, and creator funds | portfolio:read |
| Manage webhooks | webhooks:manage |
Companion packages
@probleeprotocol/mcp— installer for the Problee MCP server in Claude Desktop / Cursor / Codex@probleeprotocol/ai— Vercel AI SDK provider that exposes Problee tools togenerateText/streamText
Links
- Live API: https://api.problee.com/api/agent/v1/
- OpenAPI spec: https://api.problee.com/api/agent/v1/openapi.json
- Agent docs: https://problee.com/for-agents
- Source: https://github.com/probleeprotocol/problee/tree/main/sdk/typescript/sdk
API stability
API stability: v1 is a contract — changes within v1 are additive only, removals and reshapes are deprecated and announced at least 90 days ahead in the signed changelog feed and on the Deprecation and Sunset response headers, and a new major runs alongside the previous one for at least 12 months. Subscribe: https://api.problee.com/api/agent/v1/changelog.atom.
Not yet public: v1 may change without notice until a public-launch date is announced. Changelog: Atom · JSON · Status · @getproblee
License
Apache-2.0
