Launch a prop firm
Publish challenge templates, deploy your PropInstance contract, take
challenge deposits, and approve payouts. Everything here is self-serve over a
firm:operate credential.
Time to live: about ten minutes of API calls, once your multisig is ready.
What you need first
Section titled “What you need first”| Prerequisite | Why |
|---|---|
A firm:operate credential |
Every call here is scoped by it. See Credentials & tokens. |
A multisig address (0x…, 40 hex) |
Owns your deployed PropInstance. Custody of firm funds stays there — the platform never holds it. |
| A fee config | entryFeeBps and payoutFeeBps are required; forfeiture BPS are optional. |
The lifecycle
Section titled “The lifecycle”create ──▶ readiness ──▶ deploy ──▶ go-live ──▶ [traders trade] ──▶ approve payoutspending_deploy (dry-run) active1. Authenticate
Section titled “1. Authenticate”curl -s https://api.troncharts.xyz/api/auth/api-token \ -H 'content-type: application/json' \ -d '{"apiKey":"'"$TC_API_KEY"'","apiSecret":"'"$TC_API_SECRET"'"}'# → { "token": "eyJ…", "tier": "…", "expiresAt": <epoch ms>, … }The mint endpoint is one of the few that resolves without a tenant. Every
/api/v1/* call below must also say which tenant it is for: send
X-Tenant-Slug: <your-slug>, or call from an origin registered on your tenant.
Miss it and you get 404 {"error":"unknown_tenant_origin"}. See
Tenancy.
2. Create the firm
Section titled “2. Create the firm”The firm starts in pending_deploy. Your tenant comes from the token — you
cannot create a firm for anyone else.
curl -s https://api.troncharts.xyz/api/v1/firms \ -H "authorization: Bearer $TOKEN" \ -H "x-tenant-slug: $TC_TENANT_SLUG" \ -H 'content-type: application/json' \ -d '{ "name": "Acme Funded", "multisigAddress": "0xYourGnosisSafe000000000000000000000000", "feeConfig": { "entryFeeBps": 500, "payoutFeeBps": 1000 }, "chainId": 42161, "supportEmail": "support@acmefunded.com", "withPaperShadow": true }'# → { "firm": { "id": "firm_…", "status": "pending_deploy", … },# "paperShadowId": "…", "seededTemplates": [ … ] }withPaperShadow: true (the default) seeds a paper twin of the firm so you can
rehearse the whole trader experience with no real money.
SDK sdk.firms.create({ name, multisigAddress, feeConfig, chainId }) ·
MCP create_firm
3. Wait for readiness
Section titled “3. Wait for readiness”Readiness is your go-live checklist. Poll until ready: true.
curl -s "https://api.troncharts.xyz/api/v1/firms/$FIRM_ID/readiness?target=mainnet" \ -H "authorization: Bearer $TOKEN" \ -H "x-tenant-slug: $TC_TENANT_SLUG"# → { "ready": false, "checks": [# { "key": "factory_configured", "ok": true, "required": true },# { "key": "observer_configured", "ok": true, "required": true },# { "key": "deployer_configured", "ok": true, "required": false },# { "key": "observer_whitelisted", "ok": true, "required": true },# { "key": "instance_deployed", "ok": false, "required": true },# { "key": "watcher_subscribed", "ok": false, "required": true },# { "key": "vault_funding_configured", "ok": false, "required": false } ] }| Check | Cleared by |
|---|---|
factory_configured, observer_configured, observer_whitelisted |
The platform (shared rails) |
instance_deployed, watcher_subscribed |
You, by deploying in step 4 |
deployer_configured |
The platform. This is the gas-only deployer key the step-4 broadcast signs with. |
vault_funding_configured |
The platform. Only firm-wallet (firm-custody) programs need it — it is unrelated to the deployer. |
SDK sdk.firms.readiness(firmId, 'mainnet') · MCP check_firm_readiness
4. Deploy your PropInstance
Section titled “4. Deploy your PropInstance”Always dry-run first — it runs the full preflight without broadcasting.
# Preflight onlycurl -s https://api.troncharts.xyz/api/v1/firms/$FIRM_ID/deploy \ -H "authorization: Bearer $TOKEN" \ -H "x-tenant-slug: $TC_TENANT_SLUG" \ -H 'content-type: application/json' \ -d '{ "target": "mainnet", "dryRun": true }'
# Broadcast — gas-only platform deployer; the instance is owned by your multisigcurl -s https://api.troncharts.xyz/api/v1/firms/$FIRM_ID/deploy \ -H "authorization: Bearer $TOKEN" \ -H "x-tenant-slug: $TC_TENANT_SLUG" \ -H 'content-type: application/json' \ -d '{ "target": "mainnet", "dryRun": false }'# → { "deployed": true, "instanceAddress": "0x…", "txHash": "0x…",# "chainId": 42161, "whitelisted": true }SDK sdk.firms.deploy(firmId, { target, dryRun }) · MCP deploy_prop_instance
5. Go live
Section titled “5. Go live”curl -s https://api.troncharts.xyz/api/v1/firms/$FIRM_ID/status \ -X PATCH \ -H "authorization: Bearer $TOKEN" \ -H "x-tenant-slug: $TC_TENANT_SLUG" \ -H 'content-type: application/json' \ -d '{ "status": "active" }'status accepts pending_deploy | active | paused | migrated. Pause any time
to stop new challenges without tearing down the instance.
SDK sdk.firms.setStatus(firmId, 'active') · MCP set_firm_status
6. Traders enter and trade
Section titled “6. Traders enter and trade”Your traders — not your operator credential — drive this half:
- Start a challenge —
POST /api/v1/prop-accounts { templateId }creates apending_paymentaccount against one of your templates. - Pay the entry fee — the trader’s wallet signs the deposit calldata from
POST /api/prop/deposit-calldata { propAccountId, amountUsdcUnits }. Funds go straight to yourPropInstance; the claim watcher flips the account toactive. - Trade — the account trades against your risk rules.
You manage what they trade against with your prop:manage scope:
/api/v1/prop-templates/*, /api/v1/risk-profiles/*,
/api/v1/trading-groups/*. See Prop account model.
7. Approve payouts
Section titled “7. Approve payouts”When a trader passes, the payout lands in your worklist. Approving records and queues it — settlement is dispatched against your instance. You are the authorisation, not the on-chain sender.
# Who's owedcurl -s https://api.troncharts.xyz/api/v1/firms/$FIRM_ID/payouts/pending \ -H "authorization: Bearer $TOKEN" \ -H "x-tenant-slug: $TC_TENANT_SLUG"
# Decidecurl -s https://api.troncharts.xyz/api/v1/firms/$FIRM_ID/payouts/$PROP_ACCOUNT_ID/decision \ -H "authorization: Bearer $TOKEN" \ -H "x-tenant-slug: $TC_TENANT_SLUG" \ -H 'content-type: application/json' \ -d '{ "decision": "approved", "amountUsd": 4200, "reason": "passed evaluation" }'SDK sdk.firms.decidePayout(firmId, propAccountId, { decision, amountUsd }) ·
MCP approve_payout
Do it all with one prompt
Section titled “Do it all with one prompt”The MCP server ships a scripted launch-firm prompt that runs create →
readiness → dry-run deploy → broadcast → re-check → go-live. It needs the
stdio server built from the monorepo — the firm-lifecycle tools it calls are
not on the Streamable HTTP endpoint. See MCP server and
Build with an AI agent.
Full contract
Section titled “Full contract”Every field and response shape is in the REST reference
under /api/v1/firms/*. Fee BPS, forfeiture rules, and status transitions are
authoritative there.