---
title: Quick Start
description: Make your first UDX request, from choosing a market to placing an order and reading its outcome.
sidebar:
  order: 2
---

## Choose an Environment

Set the base URLs once before running the examples:

```bash
export UDX_BASE_URL="https://api.uat.udx.underdogsports.com"
export UDX_WS_URL="wss://api.uat.udx.underdogsports.com/ws"
```

The user acceptance testing (UAT) environment is a production-like environment used for testing. All trading performed there uses fake funds.

See [Connecting](/reference/connecting) for every environment's endpoints.

## Pick a Market

The market catalog is public. Read it and take the `ticker` for a market whose status is `open`:

```bash
curl "${UDX_BASE_URL}/markets?status=open"
```

See [Discovering Markets](/walkthroughs/discovering-markets) for reading the catalog and order books in depth.

## Create an API Key

Open the [UDX app in the UAT environment](https://app.uat.udx.underdogsports.com/) and create an API key with access to the account you will use. Give it the `read` scope to stream market data and the `trade` scope to place orders, quotes, and RFQs. Save the API key ID and private key, then set their values in your environment:

```bash
export UDX_ACCESS_KEY="<api-key-id>"
export UDX_PRIVATE_KEY_PATH="<path-to-private-key.pem>"
```

See [Authentication](/reference/authentication) for scopes and the complete signing rules.

## Place an Order

This example uses Node.js 18 or newer and only built-in modules. Save it as `place-order.mjs`, replace the example ticker with one from an open market, then run `node place-order.mjs`.

```js place-order.mjs
import {
  constants,
  createHash,
  createPrivateKey,
  sign,
} from "node:crypto";
import { readFileSync } from "node:fs";

const baseUrl = process.env.UDX_BASE_URL;
const accessKey = process.env.UDX_ACCESS_KEY;
const privateKeyPath = process.env.UDX_PRIVATE_KEY_PATH;

if (!baseUrl || !accessKey || !privateKeyPath) {
  throw new Error(
    "Set UDX_BASE_URL, UDX_ACCESS_KEY, and UDX_PRIVATE_KEY_PATH first.",
  );
}

const method = "POST";
const path = "/orders";
const timestamp = Date.now().toString();
const body = JSON.stringify({
  ticker: "UDX-EXAMPLE-MARKET",
  client_order_id: "first-order",
  side: "buy",
  quantity: "1",
  price: "0.55",
  time_in_force: "gtc",
});

const bodyHash = createHash("sha256").update(body).digest("hex");
const message = timestamp + method + path + bodyHash;
const privateKey = createPrivateKey(
  readFileSync(privateKeyPath, "utf8"),
);
const signature = sign("sha256", Buffer.from(message), {
  key: privateKey,
  padding: constants.RSA_PKCS1_PSS_PADDING,
  saltLength: 32,
}).toString("base64");

const response = await fetch(`${baseUrl}${path}`, {
  method,
  headers: {
    "Content-Type": "application/json",
    "UDX-Access-Key": accessKey,
    "UDX-Access-Timestamp": timestamp,
    "UDX-Access-Signature": signature,
  },
  body,
});

const result = await response.json();
if (!response.ok) {
  throw new Error(`${response.status}: ${JSON.stringify(result)}`);
}

console.log(result);
```

A successful submission answers `202 Accepted` with an `order_id`. See [Place an Order](/api-reference/rest/orders/create-order) for the full request and response.

## Read the Outcome

Placement is asynchronous: poll [Get Order](/api-reference/rest/orders/get-order) with the returned `order_id` until it reads `resting`, `filled`, or `rejected`.

See [Asynchronous Writes](/reference/asynchronous-writes) for how to read outcomes and retry safely, and [Placing Orders](/walkthroughs/placing-orders) for amending and canceling what you just placed.
