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

# Quickstart

> Create a Venue key, issue your first evaluation account in the sandbox, and receive its webhook on your server.

This quickstart takes you through the core of running evaluations on trdrs. You'll create a Venue
key, make your first call, issue an evaluation account, and watch a signed webhook arrive on your
server. Use this page the first time you connect trdrs to your backend.

By the end you have an evaluation account in the sandbox that you can sign in to, and a webhook
endpoint that trdrs has delivered a real event to.

<Tip>
  Trading your own accounts programmatically? Start with the
  [programmatic quickstart](/guides/programmatic-quickstart) instead. It needs a Trading API key and
  no venue.
</Tip>

<Steps>
  <Step title="Create a Venue key">
    Sign in to [sandbox API access](https://sandbox.trdrs.co/settings/api) with your trdrs account.
    Create a venue, or select the one you already have, and create a Venue key for it. Select these
    scopes: `venue:read`, `venue:configure`, `account:issue` and `balance:write`.

    The secret is shown once. Copy it into your server's environment along with the venue ID shown
    beside it:

    ```bash theme={null}
    export TRDRS_API_BASE_URL=https://sandbox.trdrs.co
    export TRDRS_VENUE_ID=00000000-0000-0000-0000-000000000000
    export TRDRS_VENUE_KEY=trdrs_vk_sandbox_...
    ```

    A sandbox key works only against the sandbox. Keep `TRDRS_VENUE_KEY` on your server. Don't put
    a Venue key in browser code, a mobile app or a public repository, because anyone who holds it
    can configure your venue.
  </Step>

  <Step title="Make your first call">
    Read your venue. This confirms that your key, its scopes and the venue ID all line up.

    Required scope: `venue:read`.

    ```bash theme={null}
    curl --fail-with-body "$TRDRS_API_BASE_URL/api/partner/venues/$TRDRS_VENUE_ID" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY"
    ```

    The response is your venue: its `id`, its `environment` (`sandbox`), its brand under `company`,
    and whether your venue rules are on. The key works.
  </Step>

  <Step title="Set up an evaluation group">
    Every account you issue lands in a group, and a group needs a route that says where its orders
    go. For evaluations the route is `internal`: orders fill on the paper book, a simulated market
    priced from live data. Create the route, create the group, then point the group at the route.

    Required scope: `venue:configure`.

    ```bash theme={null}
    curl --fail-with-body -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$TRDRS_VENUE_ID/routes" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: quickstart-route" \
      -d '{"routeId":"paper","name":"Paper book","mode":"internal","connectionId":null,
           "externalAccountId":null,"state":"offered","collar":{"kind":"ticks","maxAdverseTicks":4},
           "feeReservePerUnit":"0","uncappedMarketAllowed":false,"expectedRevision":null}'

    curl --fail-with-body -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$TRDRS_VENUE_ID/conditions/groups" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: quickstart-group" \
      -d '{"groupId":"firm-evaluation","name":"Evaluation","override":{},"stageId":null,"expectedRevision":null}'

    curl --fail-with-body -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$TRDRS_VENUE_ID/groups/firm-evaluation/route" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: quickstart-group-route" \
      -d '{"routeId":"paper"}'
    ```

    Each write carries an `Idempotency-Key`, so running a command twice returns the first result
    instead of doing the work again. `expectedRevision: null` means you expect nothing to exist yet.
    Creating your first group also turns on venue rules, so your venue's rules apply to the
    accounts you issue into it.
  </Step>

  <Step title="Publish a risk policy">
    A risk policy is your terms for the accounts you issue: the margin an account must hold, where
    it's stopped out, and how its money is posted. An account can't be issued until a published
    policy covers it. You store a version first, then publish it to put it in force.

    Start from the complete futures policy in the example for storing a risk policy version, in the
    API reference under **Venues**. Save it as `policy.json`, then change three things: set
    `authority.venueId` to your venue ID, give the policy an id of your own that doesn't start with
    `trdrs-`, and set every `effectiveFrom` to a moment that has already passed. A term that isn't
    in force yet refuses orders until it is.

    Required scope: `venue:configure`.

    ```bash theme={null}
    curl --fail-with-body -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$TRDRS_VENUE_ID/risk-policies" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: quickstart-policy" \
      -d @policy.json

    curl --fail-with-body -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$TRDRS_VENUE_ID/risk-policies/my-futures/publications" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: quickstart-publish" \
      -d '{"version":"2026-10-01"}'
    ```

    Use your own policy id in place of `my-futures`, and the `version` from your `policy.json`.
    The publication puts that version in force for every account bound to the policy, including
    the one you're about to issue.
  </Step>

  <Step title="Issue an evaluation account">
    Issue an account the way you will when a trader buys an evaluation. For this test, issue it to
    yourself: use the email you sign in to the sandbox with, since the account goes to an existing
    trdrs sign-in.

    Required scope: `account:issue`.

    ```bash theme={null}
    curl --fail-with-body -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$TRDRS_VENUE_ID/accounts" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: quickstart-account" \
      -d '{"groupId":"firm-evaluation","email":"you@example.com","startingBalance":50000,
           "currency":"USD","riskPolicy":{"policyId":"my-futures","profile":"futures"},
           "referenceId":"quickstart-account"}'
    ```

    The response is `201` with the new `account`: its `accountId`, the `accountNumber` your trader
    sees, its `groupId`, its `balance` of `50000` and `created: true`. Save the `accountId`:

    ```bash theme={null}
    export TRDRS_ACCOUNT_ID=...
    ```

    Sign in to the [sandbox](https://sandbox.trdrs.co) as that trader. The account is in your
    account list.

    `referenceId` is your own id for this sale. Sending the same request again returns the same
    account with `created: false`, so a retry never issues a second one.
  </Step>

  <Step title="Receive a webhook">
    A webhook lets trdrs tell your server when something happens to your accounts, so you don't
    have to poll. Register an HTTPS endpoint you can watch, such as a request inspector, for the
    `balance.recorded` event.

    Required scope: `venue:configure`.

    ```bash theme={null}
    curl --fail-with-body -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$TRDRS_VENUE_ID/webhooks" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: quickstart-webhook" \
      -d '{"url":"https://your-server.example.com/trdrs","events":["balance.recorded"]}'
    ```

    The response is the `webhook`, with its `id` and a `secret` that starts with `trdrs_whsec_`.
    Store the secret on your server: it's how you prove each delivery came from trdrs.

    Now credit the account. This records a balance operation and sends a `balance.recorded` event
    to your endpoint.

    Required scope: `balance:write`.

    ```bash theme={null}
    curl --fail-with-body -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$TRDRS_VENUE_ID/accounts/$TRDRS_ACCOUNT_ID/balance" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: quickstart-credit-1" \
      -d '{"op":"credit","amount":500}'
    ```

    Within about 15 seconds a `POST` arrives at your endpoint:

    ```json theme={null}
    {
      "type": "balance.recorded",
      "createdAt": "2026-09-28T12:00:00.000Z",
      "data": { "accountNumber": "EVAL-7C21A9", "op": "credit", "amount": 500, "currency": "USD", "referenceId": "quickstart-credit-1" }
    }
    ```

    It carries a `trdrs-signature` header of the form `t=<unix seconds>,v1=<hex>`. The `v1` value is
    an HMAC-SHA256 of `<t>.<raw body>` keyed with your webhook secret. Recompute it, compare in
    constant time, and refuse a timestamp more than five minutes old.
    [Receive events](/guides/receive-events) covers signatures, retries and the delivery log.

    Your integration works.
  </Step>
</Steps>

## Test it end to end

Everything above ran in the sandbox, which is separate from production: its keys, venues, accounts
and balances never cross over. Before you build on it, check the parts you'll rely on.

* **Retry a write.** Send the issue request again with the same `Idempotency-Key` and body. You get
  the same account back and nothing new is issued.
* **Send a test ping.** `POST /api/partner/venues/{venueId}/webhooks/{webhookId}/test` with an empty
  JSON body delivers a signed ping right away and tells you what your endpoint answered.
* **Read the delivery log.** `GET /api/partner/venues/{venueId}/webhooks/{webhookId}/deliveries`
  shows every attempt, so you can see a delivery your server missed.
* **Trade the account.** Activate an instrument for your venue ([Run a venue](/guides/run-a-venue)
  shows how), then sign in as the trader and place an order to see your rules applied.

If a step fails, the status and the `error` code tell you why. Venue routes answer
`{ "error": "<code>" }`.

| You get | It means | What to do |
| - | - | - |
| `401` | The key is missing, malformed, revoked or expired | Check `TRDRS_VENUE_KEY` and that `TRDRS_API_BASE_URL` is the sandbox |
| `403` | The key doesn't carry the scope the call needs | Create a key with the scopes listed in the first step |
| `404` | The venue ID isn't the one your key was created for, or the path is wrong | Check `TRDRS_VENUE_ID` against API access |
| `404` `no_user_with_that_email` | No trdrs sign-in uses that email | Issue to an email that has signed in to the sandbox |
| `409` `group_has_no_route` | The group doesn't point at a route | Run the last command of "Set up an evaluation group" |
| `409` `risk_policy_unpublished` | No publication names the policy | Publish the version you stored |
| `409` `risk_policy_profile_not_offered` | The policy has no pool for the class you named | Issue with the class your policy covers, `futures` here |
| `409` `idempotency_conflict` | You reused an `Idempotency-Key` or `referenceId` with a different request | Use a new key for a new request |

[Errors](/api/errors) lists every status the API answers.

<a id="set-up-your-venue" />

<a id="connect-registrations" />

<a id="wire-orders-carefully" />

<a id="chart-data" />

<a id="pass-conformance" />

<a id="agent-prompt" />

## Now build what you came for

You have a venue that issues evaluation accounts and a server that hears about them. From here,
pick the guide for what you're building. If you work with a coding agent, the
[agent prompts](/sdks/agent-prompts) follow the same steps.

<CardGroup cols={2}>
  <Card title="Run evaluations" icon="trophy" href="/guides/prop-firms-overview">
    Add a stage so an account is judged by your profit target and drawdown rule, and advance the traders who pass.
  </Card>

  <Card title="Run your venue" icon="building" href="/guides/run-a-venue">
    Choose the instruments your accounts trade, what they're charged and the limits that protect them.
  </Card>

  <Card title="Pre-register traders for Connect" icon="link" href="/guides/register-an-account">
    Put a trader's account in Connect, the account picker, before they sign in.
  </Card>

  <Card title="Build a business" icon="briefcase" href="/guides/business-quickstart">
    Bring in your team, choose the back office or your own backend, and plan your move to production.
  </Card>
</CardGroup>
