botso.ai API Documentation
REST API for enterprise, business, personal, teams, and clubs — partners and apps building on shared autonomous trading bots. Members buy pool tickets; stakes fund strategies with payments, payouts, and a transparent paper trail.
Overview
The botso.ai platform API is a Laravel REST service. The hostname is api.botso.ai; Laravel mounts all JSON routes under an /api prefix, so the client base URL is https://api.botso.ai/api and paths look like /v1/auth/login (full URL: https://api.botso.ai/api/v1/auth/login). Authentication uses Laravel Passport (OAuth2 bearer tokens).
| Environment | Base URL |
|---|---|
| Production | https://api.botso.ai/api |
Core concepts
| Concept | Description |
|---|---|
| Organization | Tenant (enterprise, business, team, club, or personal). Users may belong to multiple orgs. |
| Pool | Shared bot group with ticket cap, funding target, and lifecycle (draft → sim → funded → live). |
| Ticket | Equal share entitlement in a pool (not a payment rail). Status: active, pending, revoked. |
| Checkout | Live Revolut Merchant Hosted Checkout for pool tickets, desk capital seats, subscriptions, and the public shop. Webhooks finalize payment; Passport (console) or shop auth starts the session. |
| Shared bot | Fixed-strategy trading bot linked to a pool (SIM or LIVE). |
Authentication
Password grant (user apps)
For SPAs and mobile apps where a user signs in with email and password.
Issue a bearer token. User must have botso_access permission.
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "admin@botso.ai",
"password": "password",
"client_id": "YOUR_OAUTH_CLIENT_ID"
}
{
"token_type": "Bearer",
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"expires_at": "2026-06-08 12:00:00",
"scopes": ["botso:read"],
"user": {
"id": 1,
"name": "Club Admin",
"email": "admin@botso.ai",
"permissions": ["botso_access", "botso_manage"],
"organizations": [{ "id": 1, "name": "Demo Club", "slug": "botso-ai" }]
}
}
Client credentials (machine-to-machine)
For server-side integrations and service accounts. Use the botso Service Client OAuth client.
{
"client_id": "SERVICE_CLIENT_ID",
"client_secret": "SERVICE_CLIENT_SECRET",
"scope": "botso:read"
}
Session endpoints
Current user profile, roles, permissions, organizations.
Update name, phone, social handles.
Communication preferences.
Verify phone on WhatsApp.
Change password.
Revoke current access token.
Required headers
| Header | When | Example |
|---|---|---|
Authorization | All authenticated routes | Bearer <access_token> |
X-Botso-Organization | User has multiple clubs | botso-ai |
Accept | Always | application/json |
Content-Type | POST/PUT/PATCH bodies | application/json |
Organization resolution order: subdomain ({slug}.botso.ai) → X-Botso-Organization header → ?org= query → auto-select if user has one org.
Organizations
List organizations the authenticated user belongs to. No org header required.
Admin detail for the current organization (requires org context).
Search users to add as pool members.
Self-serve private syndicates
Any authenticated member (botso_access) can create their own private organization and become its owner, then invite friends and sell tickets. Creation is gated on club-catalog product seat availability — when all seats are sold out, the UI shows the create button disabled and these endpoints refuse creation.
Club-channel products with free seat counts. No org header required.
{
"can_create": true,
"products": [
{
"id": 4,
"slug": "club-the-dub",
"title": "The Dub",
"price": 300,
"currency": "EUR",
"available": 48,
"inventory_cap": 50
}
]
}
Create a private syndicate org + first pool. Caller becomes org owner and pool owner. Requires a club product with available > 0. Minimum ticket_cap is 2. No org header required.
{
"name": "Dublin lads pool",
"product_id": 4,
"ticket_cap": 4,
"profit_target": 500,
"description": "Optional"
}
{
"organization": {
"id": 12,
"slug": "dublin-lads-pool",
"name": "Dublin lads pool",
"role": "owner",
"visibility": "private",
"platform_fee_pct": 8,
"org_commission_pct": 0
},
"pool": { "slug": "dublin-lads-pool", "type": "private_syndicate", "…" },
"organizations": [ "…" ]
}
Dashboard deep link: https://dashboard.botso.ai/syndicates/create. After create, switch to the new org slug via X-Botso-Organization and use org-manage routes to invite members and assign tickets.
Shop products (desk & club catalogs)
Ticket products have a channel: desk (solo capital seats) or club (syndicate funding products). Availability is free inventory seats (ticketing_tickets.tck_avail = 0).
Authenticated console / desk catalog. Default channel is desk. Use channel=club for syndicate products.
List desk capital orders for the current user. Detail: GET /v1/botso/desk-orders/{ref}, invoice: GET /v1/botso/desk-orders/{ref}/invoice.
Public marketing shop catalog (same product shape). Club products are typically priced ~50% above desk equivalents. Single product: GET /v1/shop/products/{slug}.
When a club pool reaches its funding target, one club-product seat is sold idempotently (payment_method: club_pool). Creating a syndicate or pool that references a sold-out product returns 422.
Public shop API (/v1/shop/*)
The marketing shop at www.botso.ai/shop uses a separate shop auth guard (auth:shop / ticketing users), not Passport. After paid checkout, POST /v1/shop/orders/{ref}/desk-handoff can provision desk access and return an SSO code for the client console.
Create shop account.
Shop session token.
Cart by session_key. Authenticated: add/update/remove items, promo codes.
Start Revolut checkout for the cart. Body: session_key, optional redirect_url. Returns token, checkout_url, order_id, shop_order.
Complete a zero-total cart (promo) without Revolut.
Order history. Detail / invoice: /orders/{ref}, /orders/{ref}/invoice.
After payment: credit desk capital and return SSO for dashboard / desk auto-login.
Checkout & Revolut payments
Card and hosted checkout run on Revolut Merchant (live). Clients start a session with a bearer token; Revolut collects payment; POST /v1/webhooks/revolut (signature-verified, no user auth) finalizes tickets, capital seats, shop orders, or subscriptions.
POST …/checkout/… → open checkout_url / Revolut widget with token → webhook activates entitlement. Terms agreement is enforced in the official UI before Pay is enabled.
Pool ticket checkout (dashboard / desk Passport)
Start Hosted Checkout for a pool ticket. Creates a pending commitment when needed. Optional body: ticket_id, redirect_url, share_contact_with_members. SIM pools reject payment (422). Private / non-public pools require an existing pending ticket_id.
{
"checkout_url": "https://checkout.revolut.com/…",
"order_id": "…",
"token": "…",
"currency": "EUR",
"amount": 300,
"ticket_id": 42,
"payment_id": 99,
"public_key": "pk_…",
"mode": "prod"
}
Create / refresh a pending ticket commitment before checkout (used by commit-ticket UI). Related: GET /v1/botso/open-ticket-pools, GET /v1/botso/my-ticket-commitments, GET /v1/botso/tickets/{ticketId}/payment-details. Admins confirm offline commits with POST …/ticket-commitments/{ticketId}/confirm.
Desk capital checkout
Pay for a desk capital / product seat on the pool. Body: optional product_id, amount (min €100 when no product), redirect_url, share_contact_with_members. Returns checkout token plus payment_id, funding_id, and product metadata.
Organization subscription
Subscription status for the current org (provider: revolut).
Start subscription checkout. Optional redirect_url / success_url / cancel_url.
Cancel the org subscription.
Abandon an incomplete subscription setup.
Webhook
Revolut Merchant webhook. No bearer token — signature verified server-side. Same path on api.botso.ai (and pauliemarket). Activates tickets, capital funding, shop orders, and subscription state.
Admins can still assign tickets after off-platform payment via POST /v1/botso/pools/{slug}/tickets (entry_method: admin | cash | transfer | revolut | ticketing | usdc) or record rows with POST …/payments.
Pools — read (members & admins)
Requires botso_access and organization context. Members only see pools they belong to or hold tickets in.
List pools for current organization.
Full pool detail including bots and settings.
Dashboard metrics: PnL, per-ticket payout, chart series.
Daily pool PnL for charting — one point per trading day, no individual trade detail. Query: ?month=YYYY-MM (defaults to current month). Month is clamped to months with trading data from the pool's first record through today.
daily_pnl and month_total_pnl are gross bot realized PnL (before platform fees, tax, and per-ticket splits). cumulative_pnl is the running total within the selected month. Member earnings are lower — see /earnings.
{
"has_financial_data": true,
"month": "2026-06",
"first_trade_date": "2026-06-06",
"available_months": [
{ "value": "2026-06", "label": "June 2026" }
],
"series": [
{ "date": "2026-06-06", "daily_pnl": 56.44, "cumulative_pnl": 56.44 },
{ "date": "2026-06-07", "daily_pnl": 116.29, "cumulative_pnl": 172.73 },
{ "date": "2026-06-08", "daily_pnl": 104.59, "cumulative_pnl": 277.32 }
],
"point_count": 3,
"month_total_pnl": 277.32,
"pool": {
"slug": "sim-trial",
"name": "Trial Pool"
}
}
When the pool has no financial data or primary bot, returns has_financial_data: false with empty series and available_months.
Pool members and ticket holders.
All tickets in pool.
Payout history.
Member earnings. Optional ?user_id=.
Toggle contact sharing with other members.
Pools — manage (org admin)
Requires botso.org.manage — organization admin or owner, or platform botso_manage.
Create a pool inside the current organization. Club orgs require product_id from the club catalog with available seats. Types: club, enterprise, private_syndicate.
{
"name": "Summer Syndicate",
"type": "club",
"product_id": 4,
"ticket_cap": 4,
"profit_target": 500,
"start_date": "2026-07-01",
"end_date": "2026-12-31",
"description": "Optional pool description"
}
Funding target and share price are derived from the product price ÷ ticket cap. Sold-out products return 422.
Update entry mode, caps, dates, assignment flags.
Active pool accepting new tickets.
Admin-assign one ticket. Auto-creates next pool when cap reached.
{
"user_id": 42,
"member_name": "Jane Smith",
"target_pool_slug": "late90s-club",
"entry_method": "ticketing",
"payment_note": "FT-order-88421"
}
entry_method: admin | cash | transfer | revolut | ticketing | usdc
Add member to pool.
Club user directory.
Create club user account.
Organization audit trail.
Payments & funding (manual / admin)
For offline settlement and treasury ops. Member card checkout is under Checkout & Revolut.
Record pooled capital transfer to activate shared bots.
{
"amount": 500,
"method": "transfer",
"reference": "REV-2026-001"
}
List recorded payments.
Record off-platform payment (cash, Revolut, etc.).
Payouts & earnings
Settle a payout period for the pool.
Allocate earnings to a member.
Platform: manual SIM payout allocation (LIVE via artisan CLI).
Notifications (Twilio & WhatsApp)
Save WhatsApp Cloud API credentials for club alerts.
Analytics & trading (operator)
Requires botso_manage and user_management_access.
Shared bots in pool with session PnL.
Recent closed trades.
Summary, daily PnL series, recent trades. Query: session_name, days, limit.
Separate trading API
Operator trading endpoints at /v1/trading/* require scope trading:read.
Errors & status codes
| Code | Meaning |
|---|---|
401 | Missing or expired token — re-authenticate. |
403 | Valid token but insufficient permission or wrong org. |
404 | Pool or resource not found. |
422 | Validation error — see errors object in body. |
{
"message": "Validation error.",
"errors": {
"entry_method": ["The selected entry method is invalid."]
}
}