Create a prop firm challenge template
A template is what a trader actually buys: an account size, an entry fee, a
payout split, and the rule set the engine judges the run against. When this is
done you have an active template that can be sold as a
paper prop account immediately.
-
Collect the firm and trading group ids
Section titled “Collect the firm and trading group ids”A template belongs to one firm (
propTenantId) and allocates to one trading group (tradingGroupId). Both are required on create.Terminal window curl -s https://api.troncharts.xyz/api/v1/trading-groups \-H "authorization: Bearer $TOKEN" \-H "x-tenant-slug: $TC_TENANT_SLUG"# → { "groups": [ { "id": "…", "slug": "crypto-perps", "isDefault": true, … } ] }const { groups } = await sdk.tradingGroups.list()const { firms } = await sdk.firms.list() // needs firm:operate -
Write the rule set
Section titled “Write the rule set”rulesis a discriminated union keyed ontype, one to 32 entries of{ type, value }. An unknowntypefails the body parse with a 400invalid_body, so pick from the catalog rather than inventing a field.[{ "type": "max_drawdown_usd", "value": 1250 },{ "type": "profit_target_usd", "value": 2000 },{ "type": "min_trading_days", "value": 3 }]_usdrules take a plain number in the template’s currency. Every_pctrule takes a 0..1 fraction —max_concentration_pct: 0.3is 30%.The template is the only place you write these. The server materializes a managed risk profile holding them and binds it, so you never create or name a profile for a single program — see How an account is configured.
-
Create the template
Section titled “Create the template”idis yours to choose and must be lower-kebab-case.accountSizeUsd,feeUsdandpayoutSplitPctare decimal strings, not numbers.Terminal window curl -s https://api.troncharts.xyz/api/v1/prop-templates \-H "authorization: Bearer $TOKEN" \-H "x-tenant-slug: $TC_TENANT_SLUG" \-H 'content-type: application/json' \-d '{"id": "acme-25k-two-step","name": "Acme 25K Evaluation","accountSizeUsd": "25000.00","feeUsd": "199.00","payoutSplitPct": "80","durationDays": 30,"propTenantId": "'"$FIRM_ID"'","tradingGroupId": "'"$GROUP_ID"'","rules": [{ "type": "max_drawdown_usd", "value": 1250 },{ "type": "profit_target_usd", "value": 2000 }]}'# → 201 { "template": { "id": "acme-25k-two-step", "active": true, … } }const { template } = await sdk.propTemplates.create({id: 'acme-25k-two-step',name: 'Acme 25K Evaluation',accountSizeUsd: '25000.00',feeUsd: '199.00',payoutSplitPct: '80',propTenantId: firmId,tradingGroupId: groupId,rules: [{ type: 'max_drawdown_usd', value: 1250 },{ type: 'profit_target_usd', value: 2000 },],}) -
Confirm it is sellable
Section titled “Confirm it is sellable”The response carries
active: true. Re-read the catalogue to see it beside the rest, then handidandpropTenantIdtocreate-prop.Terminal window curl -s "https://api.troncharts.xyz/api/v1/prop-templates?activeOnly=true" \-H "authorization: Bearer $TOKEN" \-H "x-tenant-slug: $TC_TENANT_SLUG"const { templates } = await sdk.propTemplates.list({ activeOnly: true })
Sharing one rule set across templates
Section titled “Sharing one rule set across templates”Instead of rules, send riskProfileId to point several templates at one
authored profile — useful when three account sizes share the same limits. The
profile’s rules are copied down into the template, so the snapshot each account
freezes still matches exactly.
const { profile } = await sdk.riskProfiles.create({ name: 'Acme 1-step', kind: 'challenge', rules: [{ type: 'max_drawdown_usd', value: 1250 }],})await sdk.propTemplates.create({ /* … */ riskProfileId: profile.id })Other optional fields worth knowing: programKind (challenge or flash), and
either nextStepTemplateId or tierLadder — never both.
Next: Sell a paper prop account · Create a trading group · Prop account model