Zabili B2B API
Embed Zabili's binary prediction markets directly into your product. Your users predict outcomes, win rewards — you earn a revenue share on every trade.
https://api.zabili.com/partner/v1
Integration Models
Choose the integration depth that fits your product:
Widget Embed
Paste 3 lines of HTML. A fully-featured prediction market iFrame appears on your site. Zero backend work required.
API White-Label
Build your own UI. Use our REST API for markets, trading, and payouts. Full control over UX and branding.
Getting Credentials
Contact your Zabili account manager to get your partner credentials. You will receive:
- API Key — public identifier, safe to use in browser (starts with
pk_) - API Secret — private key for server-side requests only. Never expose this in browser/frontend code.
Widget Embed — Quickstart
Add the following to any page where you want the Zabili widget to appear:
<!-- 1. Add the container -->
<div id="zabili-widget"
data-partner="YOUR_API_KEY"
data-event="OPTIONAL_EVENT_ID"
data-frontend="https://app.zabili.com">
</div>
<!-- 2. Load the SDK -->
<script src="https://api.zabili.com/partner.js"></script>
That's it. The widget loads, authenticates with your API key, and renders live prediction markets inside an iFrame.
Widget Options
Configure the widget via data-* attributes on the container div:
https://app.zabili.com.Widget JS Events
The widget dispatches custom events on its container element. Listen with standard DOM event listeners:
const widget = document.getElementById('zabili-widget');
// Fired when a user places a trade
widget.addEventListener('zabili:trade.placed', (e) => {
console.log('Trade placed:', e.detail);
// { marketId, outcome, shares, price, cost }
});
// Fired when a market settles
widget.addEventListener('zabili:market.settled', (e) => {
console.log('Market settled:', e.detail);
// { marketId, outcome, payoutAmount }
});
REST API — Authentication
All API requests must be authenticated. There are two auth levels:
Partner Auth (server-side)
Used for admin-level operations and issuing user tokens. Requires both API Key and Secret. Only call from your server — never from a browser.
Authorization: Bearer YOUR_API_KEY:YOUR_API_SECRET
Partner Key Only (read-only, browser-safe)
Safe to use in browser code. Grants read-only access to markets.
X-Partner-Key: YOUR_API_KEY
# or as a query param:
GET /markets?apiKey=YOUR_API_KEY
User Token (per-user operations)
Exchange an external user ID for a Zabili JWT. Use this for trading endpoints. Token exchange must happen server-side.
Authorization: Bearer USER_JWT
SSO — User Token Exchange
Your backend calls this to get a Zabili user token for each of your users. This bridges your user identity into Zabili's system without requiring them to create an account.
/auth/tokenAuth: Partner Auth (API Key + Secret) — server-side only
// Request
POST https://api.zabili.com/partner/v1/auth/token
Authorization: Bearer pk_abc123:sk_xyz789
{
"external_user_id": "user_42",
"display_name": "Alice"
}
// Response
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600
}
}
Markets
Fetch live and upcoming prediction markets.
| Endpoint | Auth | Description |
|---|---|---|
| GET /markets | Key Only | List all open markets |
| GET /markets/:id | Key Only | Market detail with order book snapshot |
GET https://api.zabili.com/partner/v1/markets
X-Partner-Key: pk_abc123
// Response
{
"success": true,
"data": {
"markets": [
{
"id": "clq8x...",
"name": "Will Arsenal win this weekend?",
"yes_price": 0.64,
"no_price": 0.36,
"end_date": "2026-08-10T18:00:00Z",
"resolution_state": "PENDING"
}
]
}
}
Trading
Place trades on behalf of your users. Requires a user token obtained via the SSO endpoint.
/markets/:id/tradeAuth: User Token
// Request
POST https://api.zabili.com/partner/v1/markets/clq8x.../trade
Authorization: Bearer USER_JWT
{
"outcome": "YES",
"shares": 10,
"price": 0.64
}
// Response
{
"success": true,
"data": {
"orderId": "ord_789...",
"outcome": "YES",
"shares": 10,
"price": 0.64,
"cost": 6.40,
"status": "FILLED"
}
}
402 if the pool is insufficient.
Account
| Endpoint | Auth | Description |
|---|---|---|
| GET /account/balance | User Token | Pool balance + user's open positions |
| GET /account/history | User Token | Paginated trade history for this user |
Webhooks
Zabili sends a POST request to your configured webhookUrl when key events happen.
Configuring a Webhook URL
Set your webhook URL via your Zabili account manager, or the admin panel under Partner Settings.
Events
trade.placed— a user placed a trade via your integrationmarket.settled— a market resolved and payouts were distributedbalance.low— your pool balance dropped below the configured thresholdping— test event (triggered via API or admin panel)
Signature Verification
Every webhook includes an X-Zabili-Signature header — an HMAC-SHA256 of the JSON body signed with your webhook secret.
const crypto = require('crypto');
function verifyWebhook(body, signature, webhookSecret) {
const expected = crypto
.createHmac('sha256', webhookSecret)
.update(body) // raw request body string (before JSON.parse)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature), Buffer.from(expected)
);
}
// In Express:
app.post('/webhooks/zabili', express.raw({ type: '*/*' }), (req, res) => {
const sig = req.headers['x-zabili-signature'];
if (!verifyWebhook(req.body.toString(), sig, process.env.ZABILI_WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
console.log('Zabili event:', event.type, event.payload);
res.sendStatus(200);
});
Error Codes
| HTTP | Code | Meaning |
|---|---|---|
| 400 | BAD_REQUEST | Missing or invalid request parameters |
| 401 | UNAUTHORIZED | Missing or invalid API key / user token |
| 402 | INSUFFICIENT_POOL | Partner pool balance is too low for this trade |
| 403 | SUSPENDED | Partner account is suspended |
| 404 | NOT_FOUND | Market or resource does not exist |
| 429 | RATE_LIMITED | Too many requests — default 200 req/min per key |
| 500 | INTERNAL_ERROR | Unexpected server error — contact support |
All error responses follow this shape:
{
"success": false,
"message": "Human-readable description of the error"
}
Testing
Use the live test playground at widget.zabili.com to try your integration before going to production:
- Enter your API Key and Secret in the credentials panel
- Browse live markets in the Markets tab
- Test the Widget embed with a copy-paste snippet
- Walk through the full API flow in the API Explorer tab
- Send a test webhook delivery to verify your endpoint
Support
If you run into issues or have questions about your integration:
- Email: partners@zabili.com
- Test playground: widget.zabili.com
- Webhook tester:
GET /webhook/test(with Partner Auth) to trigger a test event