Prediction-markets

List stored venue credentials (metadata only — never material)

GET/v1/pm/credentials

Responses

200All credentials

  • credentials object[] (required)

Example

curl -X GET https://api.cofferline.com/v1/pm/credentials \
  -H "authorization: Bearer $TOKEN"

Store a venue trade credential (verified live, sealed at rest)

POST/v1/pm/credentials

The credential is authenticated against the venue before anything is stored — an invalid key is refused. Material is sealed at rest (AES-256-GCM, bound to your tenant + venue), write-only — no endpoint returns it — and revocation zeroes the ciphertext. Every use is confined server-side to the known trading operations (order place/cancel, authenticated reads, collateral wrap), audited per use, and volume-watched (a security.alert webhook fires on anomalous usage). Know what you are handing over. Polymarket: the signer key you store is a FULL OWNER of your funder wallet (Polymarket binds each funder to exactly one signer; Safe funders are 1-of-1), so the trading-only constraint is Cofferline's application policy, not cryptography — a hypothetical compromise of the sealed store would mean control of that one funder. Use a dedicated signer EOA, keep only working trading balances in the funder, and rotate the signer (GET /v1/pm/credentials/{id}/rotation) quarterly or on personnel change. Geo-gated (451) like every prediction-market surface.

Request body

Responses

201Stored (verification passed)

  • id string (required)
  • venue "kalshi" | "polymarket" (required)
  • label string,null (required)
  • meta object,null (required)
  • created_at object (required)
  • revoked_at object (required)

400The venue rejected the credential
403EXECUTION_DISABLED — hosted Polymarket signer-key intake is disabled (#353); use the client-signed flow
451JURISDICTION_BLOCKED
503Credential sealing unconfigured

Example

curl -X POST https://api.cofferline.com/v1/pm/credentials \
  -H "authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{}'

Revoke a credential (ciphertext destroyed — nothing left to leak)

DELETE/v1/pm/credentials/{id}

Parameters

  • id in path, string (required)

Responses

200Revoked

  • id string (required)
  • venue "kalshi" | "polymarket" (required)
  • label string,null (required)
  • meta object,null (required)
  • created_at object (required)
  • revoked_at object (required)

404No such active credential

Example

curl -X DELETE https://api.cofferline.com/v1/pm/credentials/{id} \
  -H "authorization: Bearer $TOKEN"

Signer rotation calldata: swap the funder Safe's owner to a new EOA

GET/v1/pm/credentials/{id}/rotation

For Polymarket Safe funders (signature_type 2): returns the Safe swapOwner calldata that replaces the credential's stored signer with new_owner, with the owner-linked-list prevOwner parameter derived from the live on-chain owner set (the 0x…01 sentinel for a 1-of-1 Safe). Non-custodial: Cofferline never submits this transaction — you execute it from the funder Safe with your own wallet/UI, then re-store the credential with the new key and revoke the old one (revocation zeroes the sealed material). Recommended cadence: quarterly, or immediately on personnel change or suspected exposure — recommendation only; nothing is enforced server-side.

Parameters

  • id in path, string (required)
  • new_owner in query, string (required)

Responses

200swapOwner call, ready for the funder Safe

  • credential_id string (required)
  • venue "polymarket" (required)
  • funder string (required)
  • old_owner string (required)
  • new_owner string (required)
  • prev_owner string (required)
  • call object (required)
  • sequence string[] (required)
  • rotation_policy string (required)

404No such active credential
422Not rotatable (venue/funder type, or owner-set mismatch)
451JURISDICTION_BLOCKED
503Polygon RPC unavailable

Example

curl -X GET https://api.cofferline.com/v1/pm/credentials/{id}/rotation \
  -H "authorization: Bearer $TOKEN"

The credential's resting orders, venue-authoritative (reconnect recovery)

GET/v1/pm/orders

Parameters

  • credential_id in query, string (required)
  • market in query, string

Responses

200Resting orders

  • orders object[] (required)

404No active credential
429RATE_LIMITED — the PLATFORM-wide aggregate READ budget for this venue is spent, not your per-wallet one (#194). Retry per Retry-After; it refills continuously. Order placement and cancels use a separate lane and are unaffected.
451JURISDICTION_BLOCKED
503Credential sealing unconfigured

Example

curl -X GET https://api.cofferline.com/v1/pm/orders \
  -H "authorization: Bearer $TOKEN"

Route a prediction-market limit order under policy

POST/v1/pm/orders

Places a LIMIT order on Polymarket with your stored trade-scoped credential. The wallet's prediction_markets policy rules are enforced server-side with the ledger-derived exposure floor (#124) — an order the policy forbids is refused with the violated rule, never transmitted. Metered per order (base + bps) from the prepaid balance. Geo-gated (451); disabled environments answer EXECUTION_DISABLED. An operator can also switch off ONE venue platform-wide (#232): that answers EXECUTION_DISABLED naming the venue and the operator's reason, and affects only placement — cancels, cancel-all, open-order reads and fill sync keep working at a switched-off venue, so a position can always be exited.

Request body

  • venue "polymarket"
  • wallet string (required)
  • credential_id string (required)
  • condition_id string (required)
  • token_id string (required)
  • action "buy" | "sell" (required)
  • price_usd string (required)
  • size_shares string (required)
  • client_order_id string
  • state object

Responses

201Transmitted — venue order id + status

  • venue "kalshi" | "polymarket" (required)
  • order_id string (required)
  • status string (required)
  • cost_usd string (required)
  • fee_usd string (required)
  • policy_version integer (required)

402Prepaid balance cannot cover the order fee
403POLICY_VIOLATION, or EXECUTION_DISABLED — this environment, this wallet, or this venue is switched off
404No policy / no active credential
409CONFLICT — an order with this client_order_id was already attempted (#252). Nothing was transmitted now; GET /v1/pm/orders says whether the original attempt rested.
422The venue refused the order
429RATE_LIMITED — the PLATFORM-wide aggregate order cap for this venue is spent, not your per-wallet budget (#194). Nothing was transmitted. Retry per Retry-After; the budget refills continuously. Cancels are never subject to it.
451JURISDICTION_BLOCKED
503UNAVAILABLE — credential sealing is unconfigured, the venue is misconfigured, the vendor kill switch could not be read (#232), or the server-side exposure floor could not be established (#251: position projection unreadable, or the market's position identities unresolvable). Nothing was transmitted in any case; cancels are unaffected.
504DEADLINE_EXCEEDED — the request budget was spent waiting on the venue. No order was transmitted on this attempt (#193).

Example

curl -X POST https://api.cofferline.com/v1/pm/orders \
  -H "authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"wallet":"…","credential_id":"…","condition_id":"…","token_id":"…","action":"buy","price_usd":"…","size_shares":"…"}'

Cancel every resting order for the credential (optionally one market)

DELETE/v1/pm/orders

Parameters

  • credential_id in query, string (required)
  • market in query, string

Responses

200Cancelled; ids as the venue reported them

  • venue "kalshi" | "polymarket" (required)
  • cancelled integer (required)
  • order_ids string[] (required)
  • failed_order_ids string[]
  • complete boolean (required)

403EXECUTION_DISABLED
404No active credential
422The venue refused
451JURISDICTION_BLOCKED
503Credential sealing unconfigured
504DEADLINE_EXCEEDED — the budget ran out reading the resting book, before any cancel was transmitted. A run that starts and then runs out returns 200 with complete:false instead (#193).

Example

curl -X DELETE https://api.cofferline.com/v1/pm/orders \
  -H "authorization: Bearer $TOKEN"

Prepare a client-signed Polymarket order (returns EIP-712 to sign)

POST/v1/pm/orders/prepare

The first half of the client-signed flow (#353), for Polymarket credentials you store WITHOUT a signer key. Runs every risk check the hosted route runs — jurisdiction, execution gates, the ledger-derived exposure floor (#124), your policy, the platform ceiling — then reserves the exposure and debits the fee on a durable 'prepared' order and returns the EXACT Polymarket V2 order struct plus its ready-to-sign EIP-712 payload. Sign typed_data with your own eth_signTypedData_v4 tooling (the same key that derived your stored CLOB creds) and POST the signature to /v1/pm/orders/submit before expires_at. If you never submit, the prepared order is swept and its hold + fee are released. Cofferline never receives your signer key.

Request body

  • venue "polymarket"
  • wallet string (required)
  • credential_id string (required)
  • condition_id string (required)
  • token_id string (required)
  • action "buy" | "sell" (required)
  • price_usd string (required)
  • size_shares string (required)
  • client_order_id string
  • state object

Responses

201Prepared — sign typed_data and submit

  • venue "polymarket" (required)
  • prepare_id string (required)
  • client_order_id string (required)
  • typed_data object (required)
  • order object (required)
  • cost_usd string (required)
  • fee_usd string (required)
  • policy_version integer (required)
  • expires_at object (required)

400Not a client-signed credential, or venue misconfigured
402Prepaid balance cannot cover the order fee
403POLICY_VIOLATION or EXECUTION_DISABLED
404No policy / no active credential
409CONFLICT — this client_order_id is already claimed
451JURISDICTION_BLOCKED
503UNAVAILABLE — sealing unconfigured, venue/floor unavailable
504DEADLINE_EXCEEDED

Example

curl -X POST https://api.cofferline.com/v1/pm/orders/prepare \
  -H "authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"wallet":"…","credential_id":"…","condition_id":"…","token_id":"…","action":"buy","price_usd":"…","size_shares":"…"}'

Submit a signed client-signed Polymarket order

POST/v1/pm/orders/submit

The second half of the client-signed flow (#353). Provide the prepare_id from /v1/pm/orders/prepare and your EIP-712 signature over the returned typed_data. Cofferline verifies the signature recovers to your declared signer, then relays the order to the CLOB under your trade-only credentials through the SAME coordinator admission the hosted path uses. A prepared order that already expired, or one whose signature does not recover to the declared signer, is refused and nothing is transmitted.

Request body

  • prepare_id string (required)
  • signature string (required)

Responses

201Transmitted — venue order id + status

  • venue "kalshi" | "polymarket" (required)
  • order_id string (required)
  • status string (required)
  • cost_usd string (required)
  • fee_usd string (required)
  • policy_version integer (required)

400Signature does not recover to the declared signer
404No prepared order with this id (expired, submitted, or unknown)
409The prepared order is no longer awaiting a signature
422The venue refused the order
429RATE_LIMITED — platform aggregate cap for the venue
451JURISDICTION_BLOCKED
503UNAVAILABLE — credential sealing unconfigured
504DEADLINE_EXCEEDED — nothing was transmitted

Example

curl -X POST https://api.cofferline.com/v1/pm/orders/submit \
  -H "authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"prepare_id":"…","signature":"…"}'

Cancel a resting prediction-market order

DELETE/v1/pm/orders/{venue}/{order_id}

Parameters

  • venue in path, "polymarket" (required)
  • order_id in path, string (required)
  • credential_id in query, string (required)

Responses

200Cancelled (venue-reported status)

  • venue "kalshi" | "polymarket" (required)
  • order_id string (required)
  • status string (required)

403EXECUTION_DISABLED
404No active credential
422The venue refused the cancel
451JURISDICTION_BLOCKED
503Credential sealing unconfigured
504DEADLINE_EXCEEDED — the cancel was not transmitted (#193)

Example

curl -X DELETE https://api.cofferline.com/v1/pm/orders/{venue}/{order_id} \
  -H "authorization: Bearer $TOKEN"

Polymarket trade-readiness: live approval status + missing calldata

GET/v1/pm/onboarding/{address}

Reads the six on-chain V2 grants (pUSD allowance and CTF operator approval for the V2 CTF Exchange, V2 Neg Risk Exchange, and Neg Risk Adapter) plus live pUSD/USDC.e balances for the given funds-holding wallet, and returns owner-signable calldata for any missing grants — and for the USDC.e→pUSD wrap when raw USDC.e is present (the autonomous replacement for the venue UI's confirm-funds step). Non-custodial: submitting them is your own transaction. Geo-gated like every prediction-market surface.

Parameters

  • address in path, string (required)

Responses

200Live approval statuses

  • address string (required)
  • trade_ready boolean (required)
  • approvals object[] (required)
  • collateral object (required)
  • collateral_note string (required)

451JURISDICTION_BLOCKED
503Polygon RPC unavailable

Example

curl -X GET https://api.cofferline.com/v1/pm/onboarding/{address} \
  -H "authorization: Bearer $TOKEN"

Resolve an owner EOA to its Polymarket funder Safe candidates

GET/v1/pm/funder/{owner}

Looks up every Polygon Safe the owner controls via the Safe Transaction Service, reads each candidate's six V2 trade grants and pUSD/USDC.e collateral, and names the likeliest funder (most grants set, then most pUSD). Use when the venue UI is unavailable or the agent never had one. Geo-gated like every Polymarket surface.

Parameters

  • owner in path, string (required)

Responses

200Funder candidates, best guess first

  • owner string (required)
  • funder string,null (required)
  • candidates object[] (required)

451JURISDICTION_BLOCKED
503Safe Transaction Service or Polygon RPC unavailable

Example

curl -X GET https://api.cofferline.com/v1/pm/funder/{owner} \
  -H "authorization: Bearer $TOKEN"

Journal venue fills into the wallet's ledger (idempotent)

POST/v1/pm/fills/sync

Pages the credential's fills newest-first and journals each unseen fill as a balanced double-entry group under the given wallet, stamped with the wallet's active policy hash. Re-running never double-books — the venue fill/trade id is the settlement identity. Feeds the server-side exposure floor. Polymarket journals CLOB trades (resolution redemptions are on-chain CTF events, outside this reader).

Request body

  • wallet string (required) — The treasury wallet whose books receive the fills
  • credential_id string (required)

Responses

200Sync outcome

  • journaled integer (required)
  • skipped integer (required)
  • settlements_journaled integer (required)
  • complete boolean (required)

404No policy / no active credential
451JURISDICTION_BLOCKED
503Credential sealing unconfigured

Example

curl -X POST https://api.cofferline.com/v1/pm/fills/sync \
  -H "authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"wallet":"…","credential_id":"…"}'

Wrap the funder Safe's USDC.e into pUSD (platform-relayed, no user gas)

POST/v1/pm/wrap

For Safe-type Polymarket credentials: signs approve(CollateralOnramp) + wrap() as Safe transactions with the sealed trade signer (the Safe owner) and relays them through the platform executor, which pays gas. The autonomous, API-only equivalent of the venue UI's confirm-funds step. Wraps the full unwrapped USDC.e balance unless amount_base_units narrows it.

Request body

  • credential_id string (required)
  • amount_base_units string

Responses

200Wrap executed

  • wrapped_base_units string (required)
  • txs string[] (required)
  • collateral object (required)

403EXECUTION_DISABLED — account-level platform switch
404No active credential
422Not wrappable (wrong venue/type, nothing to wrap, or revert)
451JURISDICTION_BLOCKED
503Sealing or relay signer unconfigured
504DEADLINE_EXCEEDED — the request budget ran out BEFORE a broadcast, never during one (#193). The message names any transaction that did land; an approve without its wrap is safe to retry.

Example

curl -X POST https://api.cofferline.com/v1/pm/wrap \
  -H "authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"credential_id":"…"}'