# Quick Start

Buy BTC on the True Markets Gateway.

## Prerequisites

Complete [Onboarding](/getting-started/onboarding) to create an account, fund it, and download an API key bundle. With `TM_KEY_FILE` set in your environment, you're ready to continue.

Safety first
The "Place the order" step below sends a real market order that spends real funds. Stop after the quote step on the first run to confirm everything works.

Stuck? Ask on Discord
The fastest way to unblock is the [True Markets Discord](https://discord.gg/SC92xRUZqw) — community and team hang out there for integration help. For account or network access issues, email [support@truemarkets.co](mailto:support@truemarkets.co).

## Sign your request and get a JWT

Sign `{key_id}.{timestamp}` with ES256, then POST to `/v1/auth/api-key/token` to receive a short-lived `access_token`.

Signing is language-specific cryptography. See the [Auth Service API](/apis/auth/openapi) reference.


```javascript Node.js
import { readFileSync } from "node:fs";
import { createPrivateKey, sign } from "node:crypto";

async function getToken() {
  const { key_id, private_key: jwk } = JSON.parse(
    readFileSync(process.env.TM_KEY_FILE, "utf8"),
  );
  const key = createPrivateKey({ key: jwk, format: "jwk" });

  const timestamp = Math.floor(Date.now() / 1000);
  const signature = sign(
    "SHA256",
    Buffer.from(`${key_id}.${timestamp}`),
    { key, dsaEncoding: "ieee-p1363" },
  ).toString("base64url");

  const { access_token } = await (await fetch(
    "https://api.truemarkets.co/v1/auth/api-key/token", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ key_id, timestamp, signature }),
    },
  )).json();

  return access_token;
}

const token = await getToken();
```


```python Python
import base64, json, os, time
from pathlib import Path

import requests
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature


def get_token() -> str:
    bundle = json.loads(Path(os.environ["TM_KEY_FILE"]).expanduser().read_text())
    key_id, jwk = bundle["key_id"], bundle["private_key"]
    d = int.from_bytes(base64.urlsafe_b64decode(jwk["d"] + "=="), "big")
    key = ec.derive_private_key(d, ec.SECP256R1())

    ts = int(time.time())
    der = key.sign(f"{key_id}.{ts}".encode(), ec.ECDSA(hashes.SHA256()))
    r, s = decode_dss_signature(der)
    sig = base64.urlsafe_b64encode(
        r.to_bytes(32, "big") + s.to_bytes(32, "big")
    ).rstrip(b"=").decode()

    return requests.post(
        "https://api.truemarkets.co/v1/auth/api-key/token",
        json={"key_id": key_id, "timestamp": ts, "signature": sig},
    ).json()["access_token"]


token = get_token()
```

The token is short-lived. For a production app, see [Refresh access token](/apis/auth/openapi/token). The remaining steps assume `TOKEN` is set in your environment.

## Get tradable assets

Fetch the catalog of assets available across CeFi and DeFi venues. This endpoint is public, so no token is required.

Limit orders and DeFi
Limit orders are supported only on the CeFi assets returned by this endpoint. Pass `venue=cefi` to filter to that subset, `venue=defi` for the DeFi catalog, or omit `venue` to get both.


```bash cURL
curl "https://api.truemarkets.co/v1/conductor/assets?venue=cefi"
```


```javascript JavaScript
const assets = await (await fetch(
  "https://api.truemarkets.co/v1/conductor/assets?venue=cefi",
)).json();
```


```javascript Node.js
const assets = await (await fetch(
  "https://api.truemarkets.co/v1/conductor/assets?venue=cefi",
)).json();
```


```python Python
import requests

assets = requests.get(
    "https://api.truemarkets.co/v1/conductor/assets",
    params={"venue": "cefi"},
).json()
```


```java Java
HttpResponse<String> response = HttpClient.newHttpClient().send(
    HttpRequest.newBuilder()
        .uri(URI.create("https://api.truemarkets.co/v1/conductor/assets?venue=cefi"))
        .GET()
        .build(),
    HttpResponse.BodyHandlers.ofString());
```


```csharp C#
using System.Net.Http;
using System.Net.Http.Json;

var http = new HttpClient();
var assets = await http.GetFromJsonAsync<object>(
    "https://api.truemarkets.co/v1/conductor/assets?venue=cefi");
```


```php PHP
<?php
$ch = curl_init('https://api.truemarkets.co/v1/conductor/assets?venue=cefi');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$assets = json_decode(curl_exec($ch), true);
```


```go Go
package main

import (
    "io"
    "net/http"
)

res, _ := http.Get("https://api.truemarkets.co/v1/conductor/assets?venue=cefi")
defer res.Body.Close()
assets, _ := io.ReadAll(res.Body)
```


```ruby Ruby
require 'json'; require 'net/http'; require 'uri'

uri = URI('https://api.truemarkets.co/v1/conductor/assets')
uri.query = URI.encode_www_form(venue: 'cefi')
res = Net::HTTP.get_response(uri)
assets = JSON.parse(res.body)
```


```r R
library(httr); library(jsonlite)

assets <- GET("https://api.truemarkets.co/v1/conductor/assets",
              query = list(venue = "cefi"))
content(assets)
```

## Get a trade quote

Fetch a quote without committing. `qty_unit: "quote"` means "$5 of BTC"; use `"base"` to specify a BTC amount instead.


```bash cURL
curl -X POST https://api.truemarkets.co/v1/conductor/quotes \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "base_asset": "BTC",
    "quote_asset": "USDC",
    "qty": "5",
    "qty_unit": "quote",
    "side": "buy"
  }'
```


```javascript JavaScript
const quote = await (await fetch("https://api.truemarkets.co/v1/conductor/quotes", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    base_asset: "BTC",
    quote_asset: "USDC",
    qty: "5",
    qty_unit: "quote",
    side: "buy",
  }),
})).json();
```


```javascript Node.js
const quote = await (await fetch("https://api.truemarkets.co/v1/conductor/quotes", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    base_asset: "BTC",
    quote_asset: "USDC",
    qty: "5",
    qty_unit: "quote",
    side: "buy",
  }),
})).json();
```


```python Python
import os, requests

quote = requests.post(
    "https://api.truemarkets.co/v1/conductor/quotes",
    headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
    json={
        "base_asset": "BTC",
        "quote_asset": "USDC",
        "qty": "5",
        "qty_unit": "quote",
        "side": "buy",
    },
).json()
```


```java Java
String body = """
    {
      "base_asset": "BTC",
      "quote_asset": "USDC",
      "qty": "5",
      "qty_unit": "quote",
      "side": "buy"
    }""";

HttpResponse<String> response = HttpClient.newHttpClient().send(
    HttpRequest.newBuilder()
        .uri(URI.create("https://api.truemarkets.co/v1/conductor/quotes"))
        .header("Authorization", "Bearer " + System.getenv("TOKEN"))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(body))
        .build(),
    HttpResponse.BodyHandlers.ofString());
```


```csharp C#
using System.Net.Http;
using System.Net.Http.Json;

var token = Environment.GetEnvironmentVariable("TOKEN");
var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);

var quote = await http.PostAsJsonAsync(
    "https://api.truemarkets.co/v1/conductor/quotes",
    new {
        base_asset = "BTC",
        quote_asset = "USDC",
        qty = "5",
        qty_unit = "quote",
        side = "buy",
    });
```


```php PHP
<?php
$ch = curl_init('https://api.truemarkets.co/v1/conductor/quotes');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode([
        'base_asset' => 'BTC',
        'quote_asset' => 'USDC',
        'qty' => '5',
        'qty_unit' => 'quote',
        'side' => 'buy',
    ]),
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('TOKEN'),
        'Content-Type: application/json',
    ],
    CURLOPT_RETURNTRANSFER => true,
]);
$quote = json_decode(curl_exec($ch), true);
```


```go Go
package main

import (
    "bytes"
    "encoding/json"
    "io"
    "net/http"
    "os"
)

body, _ := json.Marshal(map[string]string{
    "base_asset":  "BTC",
    "quote_asset": "USDC",
    "qty":         "5",
    "qty_unit":    "quote",
    "side":        "buy",
})

req, _ := http.NewRequest("POST",
    "https://api.truemarkets.co/v1/conductor/quotes",
    bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("TOKEN"))
req.Header.Set("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
quote, _ := io.ReadAll(res.Body)
```


```ruby Ruby
require 'json'; require 'net/http'; require 'uri'

uri = URI('https://api.truemarkets.co/v1/conductor/quotes')
req = Net::HTTP::Post.new(uri,
  'Authorization' => "Bearer #{ENV['TOKEN']}",
  'Content-Type'  => 'application/json')
req.body = JSON.generate(
  base_asset: 'BTC', quote_asset: 'USDC',
  qty: '5', qty_unit: 'quote', side: 'buy')

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
quote = JSON.parse(res.body)
```


```r R
library(httr); library(jsonlite)

quote <- POST("https://api.truemarkets.co/v1/conductor/quotes",
  add_headers(Authorization = paste("Bearer", Sys.getenv("TOKEN"))),
  body = toJSON(list(
    base_asset = "BTC",
    quote_asset = "USDC",
    qty = "5",
    qty_unit = "quote",
    side = "buy"
  ), auto_unbox = TRUE),
  content_type_json())
content(quote)
```

## Place the order

Same shape as the quote, plus `type: "market"`. Returns an `order_id` to track status.

This sends a real order
Steps 1–2 only read. The request below moves real funds.


```bash cURL
curl -X POST https://api.truemarkets.co/v1/conductor/orders \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "base_asset": "BTC",
    "quote_asset": "USDC",
    "qty": "5",
    "qty_unit": "quote",
    "side": "buy",
    "type": "market"
  }'
```


```javascript JavaScript
const order = await (await fetch("https://api.truemarkets.co/v1/conductor/orders", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    base_asset: "BTC",
    quote_asset: "USDC",
    qty: "5",
    qty_unit: "quote",
    side: "buy",
    type: "market",
  }),
})).json();
```


```javascript Node.js
const order = await (await fetch("https://api.truemarkets.co/v1/conductor/orders", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    base_asset: "BTC",
    quote_asset: "USDC",
    qty: "5",
    qty_unit: "quote",
    side: "buy",
    type: "market",
  }),
})).json();
```


```python Python
order = requests.post(
    "https://api.truemarkets.co/v1/conductor/orders",
    headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
    json={
        "base_asset": "BTC",
        "quote_asset": "USDC",
        "qty": "5",
        "qty_unit": "quote",
        "side": "buy",
        "type": "market",
    },
).json()
```


```java Java
String body = """
    {
      "base_asset": "BTC",
      "quote_asset": "USDC",
      "qty": "5",
      "qty_unit": "quote",
      "side": "buy",
      "type": "market"
    }""";

HttpResponse<String> response = HttpClient.newHttpClient().send(
    HttpRequest.newBuilder()
        .uri(URI.create("https://api.truemarkets.co/v1/conductor/orders"))
        .header("Authorization", "Bearer " + System.getenv("TOKEN"))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(body))
        .build(),
    HttpResponse.BodyHandlers.ofString());
```


```csharp C#
var order = await http.PostAsJsonAsync(
    "https://api.truemarkets.co/v1/conductor/orders",
    new {
        base_asset = "BTC",
        quote_asset = "USDC",
        qty = "5",
        qty_unit = "quote",
        side = "buy",
        type = "market",
    });
```


```php PHP
<?php
$ch = curl_init('https://api.truemarkets.co/v1/conductor/orders');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode([
        'base_asset' => 'BTC',
        'quote_asset' => 'USDC',
        'qty' => '5',
        'qty_unit' => 'quote',
        'side' => 'buy',
        'type' => 'market',
    ]),
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('TOKEN'),
        'Content-Type: application/json',
    ],
    CURLOPT_RETURNTRANSFER => true,
]);
$order = json_decode(curl_exec($ch), true);
```


```go Go
body, _ := json.Marshal(map[string]string{
    "base_asset":  "BTC",
    "quote_asset": "USDC",
    "qty":         "5",
    "qty_unit":    "quote",
    "side":        "buy",
    "type":        "market",
})

req, _ := http.NewRequest("POST",
    "https://api.truemarkets.co/v1/conductor/orders",
    bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("TOKEN"))
req.Header.Set("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
order, _ := io.ReadAll(res.Body)
```


```ruby Ruby
uri = URI('https://api.truemarkets.co/v1/conductor/orders')
req = Net::HTTP::Post.new(uri,
  'Authorization' => "Bearer #{ENV['TOKEN']}",
  'Content-Type'  => 'application/json')
req.body = JSON.generate(
  base_asset: 'BTC', quote_asset: 'USDC',
  qty: '5', qty_unit: 'quote', side: 'buy', type: 'market')

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
order = JSON.parse(res.body)
```


```r R
order <- POST("https://api.truemarkets.co/v1/conductor/orders",
  add_headers(Authorization = paste("Bearer", Sys.getenv("TOKEN"))),
  body = toJSON(list(
    base_asset = "BTC",
    quote_asset = "USDC",
    qty = "5",
    qty_unit = "quote",
    side = "buy",
    type = "market"
  ), auto_unbox = TRUE),
  content_type_json())
content(order)
```

## Verify the trade

Track the order with the `order_id` returned from step 3.


```bash cURL
curl https://api.truemarkets.co/v1/conductor/orders/$ORDER_ID/status \
  -H "Authorization: Bearer $TOKEN"
```


```javascript JavaScript
const status = await (await fetch(
  `https://api.truemarkets.co/v1/conductor/orders/${ORDER_ID}/status`,
  { headers: { Authorization: `Bearer ${TOKEN}` } },
)).json();
```


```javascript Node.js
const status = await (await fetch(
  `https://api.truemarkets.co/v1/conductor/orders/${process.env.ORDER_ID}/status`,
  { headers: { Authorization: `Bearer ${process.env.TOKEN}` } },
)).json();
```


```python Python
status = requests.get(
    f"https://api.truemarkets.co/v1/conductor/orders/{os.environ['ORDER_ID']}/status",
    headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
).json()
```


```java Java
HttpResponse<String> response = HttpClient.newHttpClient().send(
    HttpRequest.newBuilder()
        .uri(URI.create(
            "https://api.truemarkets.co/v1/conductor/orders/"
            + System.getenv("ORDER_ID") + "/status"))
        .header("Authorization", "Bearer " + System.getenv("TOKEN"))
        .GET()
        .build(),
    HttpResponse.BodyHandlers.ofString());
```


```csharp C#
var orderId = Environment.GetEnvironmentVariable("ORDER_ID");
var status = await http.GetFromJsonAsync<object>(
    $"https://api.truemarkets.co/v1/conductor/orders/{orderId}/status");
```


```php PHP
<?php
$orderId = getenv('ORDER_ID');
$ch = curl_init("https://api.truemarkets.co/v1/conductor/orders/$orderId/status");
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('TOKEN')],
    CURLOPT_RETURNTRANSFER => true,
]);
$status = json_decode(curl_exec($ch), true);
```


```go Go
url := "https://api.truemarkets.co/v1/conductor/orders/" + os.Getenv("ORDER_ID") + "/status"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("TOKEN"))

res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
status, _ := io.ReadAll(res.Body)
```


```ruby Ruby
uri = URI("https://api.truemarkets.co/v1/conductor/orders/#{ENV['ORDER_ID']}/status")
req = Net::HTTP::Get.new(uri,
  'Authorization' => "Bearer #{ENV['TOKEN']}")

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
status = JSON.parse(res.body)
```


```r R
status <- GET(
  paste0("https://api.truemarkets.co/v1/conductor/orders/",
         Sys.getenv("ORDER_ID"), "/status"),
  add_headers(Authorization = paste("Bearer", Sys.getenv("TOKEN"))))
content(status)
```

## Next steps

- **[Gateway API reference](/apis/gateway/openapi)** — every endpoint, schema, and error code.
- **[Auth Service API](/apis/auth/openapi)** — refresh tokens, additional auth methods (passkey, magic link, SSO).
- **[True Markets 101](/getting-started/truemarkets-101)** — when to pick CeFi Direct or DeFi Direct over Gateway.
- **[Join the Discord](https://discord.gg/SC92xRUZqw)** — chat with the team and other integrators.