> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cabalspy.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a competition

> POST /v1/competitions: create a trading competition between your platform users with chain, metric, duration, start time, participant limits and minimums.

Creates a [trading competition](https://docs.cabalspy.xyz/cabalspy-id/competitions.md) for your instance. It starts at `starts_at`, or at once, as soon as `min_participants` have joined.

> [!TIP]
>
> At most 5 competitions can be open at the same time per developer account, across all your instances. A sixth is refused with `competition_limit`.

## Body

**name** `string` *required*

Name, 1 to 100 characters.

**chain** `string` *required*

The chain traded on: solana, bnb, base, eth or rh.

**metric** `string` *required*

What ranks the traders: pnl\_usd, pnl, volume\_usd, volume, trades or win\_rate. See [Metrics](https://docs.cabalspy.xyz/cabalspy-id/competitions.md#metrics).

**duration\_hours** `number` *required*

How long it runs once started, 1 to 8760 hours (one year). Fractions are allowed.

**starts\_at** `string`

Earliest start, ISO 8601, for example `2026-11-01T18:00:00Z`. Without a time zone UTC is assumed. Leave it out to start as soon as enough participants joined.

**description** `string`

Description, at most 2,000 characters.

**enrollment** `string`

`opt_in`: you join users one by one. `all_users`: every platform user takes part.

**min\_participants** `integer`

Participants needed before it starts, 1 to 1,000,000.

**max\_participants** `integer`

Maximum participants, at least min\_participants. null for no limit.

**min\_trades** `integer`

Trades a participant needs to be ranked, 0 to 1,000,000.

**min\_volume\_usd** `number`

USD volume a participant needs to be ranked, 0 or more.

**late\_join** `boolean`

Whether users can join after the start.

**wallet\_trust** `string`

`all` or `verified_only`: whether unverified wallets count in this competition.

**prizes** `any`

Free-form JSON describing the prizes, at most 5,000 characters as JSON. Stored and returned as you send it, for display. CabalSpy ID does not pay out prizes.

Fields you leave out take their default value; the response shows every value in effect.

## Usage Example

```bash cURL theme={null}
curl -X POST "https://api-id.cabalspy.xyz/v1/competitions" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Weekend PnL Cup",
    "description": "Best realized PnL on Solana over the weekend.",
    "chain": "solana",
    "metric": "pnl_usd",
    "duration_hours": 48,
    "starts_at": "2026-11-01T18:00:00Z",
    "enrollment": "opt_in",
    "min_participants": 10,
    "max_participants": 500,
    "min_trades": 3,
    "min_volume_usd": 100,
    "late_join": true,
    "prizes": [{"rank": 1, "prize": "1,000 USDC"}, {"rank": 2, "prize": "500 USDC"}]
  }'
```

```python Python theme={null}
import requests

r = requests.post("https://api-id.cabalspy.xyz/v1/competitions", json={
    "name": "Weekend PnL Cup", "chain": "solana", "metric": "pnl_usd",
    "duration_hours": 48, "starts_at": "2026-11-01T18:00:00Z",
    "min_participants": 10, "min_trades": 3,
}, headers={"Authorization": "Bearer YOUR_KEY"})
c = r.json()["data"]
print(c["id"], c["status"], c["starts_at"])
```

```javascript JavaScript theme={null}
const res = await fetch("https://api-id.cabalspy.xyz/v1/competitions", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "Volume Sprint", chain: "base", metric: "volume_usd",
    duration_hours: 24, enrollment: "all_users",
  }),
});
const { data } = await res.json();
console.log(data.id, data.status);
```

## Response

**201** with the competition object.

**id** `string`

The competition id.

**name, description** `string`

Name and description.

**chain, chain\_name** `string`

Chain id and name.

**metric** `string`

The ranking metric.

**wallet\_trust** `string`

all or verified\_only.

**enrollment** `string`

opt\_in or all\_users.

**status** `string`

scheduled, waiting, running, ended or cancelled. See [Lifecycle](https://docs.cabalspy.xyz/cabalspy-id/competitions.md#lifecycle).

**starts\_at** `string`

Earliest start, or null.

**duration\_hours** `number`

Duration in hours.

**started\_at, ends\_at, ended\_at** `string`

Actual start, planned end and actual end. Null until they happen.

**min\_participants, max\_participants** `integer`

Participant limits. max\_participants is null for no limit.

**participants** `integer`

Current number of participants.

**min\_trades, min\_volume\_usd** `number`

Minimums to be ranked.

**late\_join** `boolean`

Whether users can join after the start.

**prizes** `any`

Your prizes JSON, or null.

**rules\_version** `integer`

Raised by one with every rule change.

**standings\_updated\_at** `string`

When the standings were last computed, or null.

**created\_at, updated\_at** `string`

Creation and last change.

**changes** `array`

Every rule change, see [Competition detail](https://docs.cabalspy.xyz/cabalspy-id/competitions-list.md#competition-detail). Empty for a new competition.

**changed\_while\_running** `boolean`

Whether a rule was changed while the competition ran.

```json Response theme={null}
{
  "success": true,
  "data": {
    "id": "9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f",
    "name": "Weekend PnL Cup",
    "description": "Best realized PnL on Solana over the weekend.",
    "chain": "solana",
    "chain_name": "Solana",
    "metric": "pnl_usd",
    "wallet_trust": "all",
    "enrollment": "opt_in",
    "status": "scheduled",
    "starts_at": "2026-11-01T18:00:00Z",
    "duration_hours": 48.0,
    "started_at": null,
    "ends_at": null,
    "ended_at": null,
    "min_participants": 10,
    "max_participants": 500,
    "participants": 0,
    "min_trades": 3,
    "min_volume_usd": 100.0,
    "late_join": true,
    "prizes": [{ "rank": 1, "prize": "1,000 USDC" }, { "rank": 2, "prize": "500 USDC" }],
    "rules_version": 1,
    "standings_updated_at": null,
    "created_at": "2026-10-26T08:04:11Z",
    "updated_at": "2026-10-26T08:04:11Z",
    "changes": [],
    "changed_while_running": false
  },
  "meta": {
    "request_id": "req_5162c7cf7f87",
    "cached": false,
    "cache_age_seconds": 0,
    "version": "v1",
    "timestamp": "2026-10-26T08:04:11Z"
  }
}
```

## Errors

| Status | Code | Meaning |
| - | - | - |
| 400 | missing\_parameter | name, chain, metric or duration\_hours missing. |
| 400 | invalid\_parameter | A field has an invalid value, or an unknown field was sent. `parameter` names it. |
| 401 | missing\_api\_key | API key missing. |
| 403 | invalid\_api\_key | API key invalid or not enabled for CabalSpy ID. |
| 409 | competition\_limit | 5 competitions are already open. |
| 429 | rate\_limit\_exceeded | Rate limit exceeded. |

See [Errors](https://docs.cabalspy.xyz/cabalspy-id/errors.md) for the full list.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.