SDK
Direct Mode
Direct exchange access without the PAPI API proxy
Direct Mode
In direct mode, the SDK connects directly to exchange APIs. No data passes through PAPI servers.
How It Works
Your App → PAPI SDK → Exchange (Polymarket/Kalshi)The SDK handles exchange-specific authentication, request formatting, and response normalization locally. You provide credentials directly.
Setup
Polymarket
Polymarket uses the CLOB API with API key, secret, and passphrase:
use papi_sdk::{PapiConfig, PapiClient, Exchange};
let config = PapiConfig::direct()
.polymarket_credentials(
"your-clob-api-key",
"your-clob-secret",
"your-passphrase",
)
.build()?;
let client = PapiClient::new(config);
let markets = client
.markets(Exchange::Polymarket)
.active(true)
.send()
.await?;Kalshi
Kalshi uses email/password authentication with session tokens:
let config = PapiConfig::direct()
.kalshi_credentials(
"your-email@example.com",
"your-password",
)
.build()?;
let client = PapiClient::new(config);
let markets = client
.markets(Exchange::Kalshi)
.status("open")
.send()
.await?;Both Exchanges
let config = PapiConfig::direct()
.polymarket_credentials("key", "secret", "passphrase")
.kalshi_credentials("email", "password")
.build()?;Environment Variables
Instead of hardcoding credentials:
export PAPI_MODE=direct
export POLYMARKET_API_KEY=your-clob-api-key
export POLYMARKET_SECRET=your-clob-secret
export POLYMARKET_PASSPHRASE=your-passphrase
export KALSHI_EMAIL=your-email@example.com
export KALSHI_PASSWORD=your-passwordlet config = PapiConfig::from_env()?;When to Use Direct Mode
Direct mode is best when:
- Latency matters — Eliminates the proxy hop through PAPI servers
- Credential control — You want credentials to stay on your infrastructure
- Offline operation — Your app should work even if PAPI servers are down
- High throughput — You need more than 60 requests per minute
Trade-offs
| Feature | Managed | Direct |
|---|---|---|
| Credential storage | Server-side (encrypted) | Client-side |
| Caching | Built-in (PostgreSQL) | None (bring your own) |
| Rate limiting | 60 req/min per key | Exchange limits apply |
| Latency | +10-50ms (proxy hop) | Direct to exchange |
| Auth complexity | One API key | Per-exchange credentials |
| PAPI dependency | Required | Not required |
Switching Modes
Since both modes use the same SDK interface, switching is a config change:
// Managed mode
let config = PapiConfig::managed()
.api_key("papi_sk_live_...")
.build()?;
// Direct mode — same client API
let config = PapiConfig::direct()
.polymarket_credentials("key", "secret", "pass")
.build()?;
// Client code stays the same
let client = PapiClient::new(config);
let markets = client.markets(Exchange::Polymarket).send().await?;