Skip to content
UDX
Esc
↑↓navigate↵open⌘Jpreview
On this page

Quick Start

Create API credentials, call a public endpoint, sign a private request, and place your first order in the UAT environment.

Choose API endpoints

Environment REST endpoint WebSocket endpoint
UAT https://api.uat.udx.underdogsports.com/ wss://api.uat.udx.underdogsports.com/ws
Production https://api.udx.underdogsports.com/ wss://api.udx.underdogsports.com/ws

Set the UAT REST base URL once before running the examples:

export UDX_BASE_URL="https://api.uat.udx.underdogsports.com"

List markets

The markets catalog is public and does not require authentication:

curl "${UDX_BASE_URL}/markets?limit=1&sort=event_date&order=asc"

Use a returned ticker to request its aggregated order book:

curl "${UDX_BASE_URL}/markets/UDX-EXAMPLE-MARKET/orderbook?depth=10"

See Pagination for additional pages and the WebSocket API for live updates.

Create an API Key

Open the UDX UAT app and create an API key with the trade scope and access to the account you will use. Save the API key ID and private key, then set their values in your environment:

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

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 returned by the markets request, then run node place-order.mjs:

import {
  constants,
  createHash,
  createPrivateKey,
  randomUUID,
  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 idempotencyKey = randomUUID();
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 + idempotencyKey;
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,
    "UDX-Idempotency-Key": idempotencyKey,
  },
  body,
});

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

console.log(result);

The timestamp is the current Unix time in milliseconds. For this first order, always send the newly generated UUID in UDX-Idempotency-Key and include its exact value in the signed message. Reuse that key only to retry this same order. See Authentication for the complete signing rules, Idempotency for optional-header behavior outside this walkthrough, and Place an order for the full request and response.